diff --git a/cmix/interface.go b/cmix/interface.go
index 3a240c9f0d6e936791b296f981e7df091eb73c31..c5d1a45dc1f00f881e78d141a68645c41e84c176 100644
--- a/cmix/interface.go
+++ b/cmix/interface.go
@@ -46,10 +46,10 @@ type Client interface {
 	// implementing a protocol on top.
 	//   recipient - cMix ID of the recipient.
 	//   fingerprint - Key Fingerprint. 256-bit field to store a 255-bit
-	//      fingerprint, highest order bit must be 0 (panic otherwise). If your
+	//      fingerprint, the highest order bit must be 0 (panic otherwise). If your
 	//      system does not use key fingerprints, this must be random bits.
 	//   service - Reception Service. The backup way for a client to identify
-	//      messages on receipt via trial hashing and to identify notifications.
+	//    messages on receipt via trial hashing and to identify notifications.
 	//      If unused, use message.GetRandomService to fill the field with
 	//      random data.
 	//   payload - Contents of the message. Cannot exceed the payload size for a
@@ -87,8 +87,8 @@ type Client interface {
 	// Will return an error if the network is unhealthy or if it fails to send
 	// (along with the reason). Blocks until successful send or err.
 	// WARNING: Do not roll your own crypto.
-	SendMany(messages []TargetedCmixMessage, p CMIXParams) (
-		rounds.Round, []ephemeral.Id, error)
+	SendMany(messages []TargetedCmixMessage,
+		params CMIXParams) (rounds.Round, []ephemeral.Id, error)
 
 	// SendWithAssembler sends a variable cmix payload to the provided recipient.
 	// The payload sent is based on the Complier function passed in, which accepts
@@ -108,6 +108,25 @@ type Client interface {
 	SendWithAssembler(recipient *id.ID, assembler MessageAssembler,
 		cmixParams CMIXParams) (rounds.Round, ephemeral.Id, error)
 
+	// SendManyWithAssembler sends variable cMix payloads to the provided recipients.
+	// The payloads sent are based on the ManyMessageAssembler function passed in,
+	// which accepts a round ID and returns the necessary payload data.
+	// Returns the round IDs of the rounds the payloads were sent or an error if it
+	// fails.
+	// This does not have end-to-end encryption on it and is used exclusively as
+	// a send operation for higher order cryptographic protocols. Do not use unless
+	// implementing a protocol on top.
+	//
+	//	recipients - cMix IDs of the recipients.
+	//	assembler - ManyMessageAssembler function, accepting round ID and returning
+	// 	            a list of TargetedCmixMessage.
+	//
+	// Will return an error if the network is unhealthy or if it fails to send
+	// (along with the reason). Blocks until successful sends or errors.
+	// WARNING: Do not roll your own crypto.
+	SendManyWithAssembler(recipients []*id.ID, assembler ManyMessageAssembler,
+		params CMIXParams) (rounds.Round, []ephemeral.Id, error)
+
 	/* === Message Reception ================================================ */
 	/* Identities are all network identities which the client is currently
 	   trying to pick up message on. An identity must be added to receive
@@ -333,13 +352,22 @@ type Client interface {
 
 type ClientErrorReport func(source, message, trace string)
 
+// ManyMessageAssembler func accepts a round ID, returning a TargetedCmixMessage.
+// This allows users to pass in a payload which will contain the
+// round ID over which the message is sent.
+type ManyMessageAssembler func(rid id.Round) ([]TargetedCmixMessage, error)
+
+// manyMessageAssembler is an internal wrapper around ManyMessageAssembler which
+// returns a list of assembledCmixMessage.
+type manyMessageAssembler func(rid id.Round) ([]assembledCmixMessage, error)
+
 // MessageAssembler func accepts a round ID, returning fingerprint, service,
-// payload & mac. This allows users to pass in a paylaod which will contain the
+// payload & mac. This allows users to pass in a payload which will contain the
 // round ID over which the message is sent.
 type MessageAssembler func(rid id.Round) (fingerprint format.Fingerprint,
 	service message.Service, payload, mac []byte, err error)
 
 // messageAssembler is an internal wrapper around MessageAssembler which
-// returns a format.message This is necessary to preserve the interaction
+// returns a format.Message This is necessary to preserve the interaction
 // between sendCmixHelper and critical messages
 type messageAssembler func(rid id.Round) (format.Message, error)
diff --git a/cmix/sendCmix.go b/cmix/sendCmix.go
index f1660588aefcb4dfa13d24856d581d74ab41e66e..ec3b7289c1aa325fe2578d347f9e5efc33a29960 100644
--- a/cmix/sendCmix.go
+++ b/cmix/sendCmix.go
@@ -70,34 +70,37 @@ func (c *client) Send(recipient *id.ID, fingerprint format.Fingerprint,
 	return c.sendWithAssembler(recipient, assembler, cmixParams)
 }
 
-// SendWithAssembler sends a variable cmix payload to the provided recipient.
-// The payload sent is based on the Complier function passed in, which accepts
-// a round ID and returns the necessary payload data.
+// SendWithAssembler sends a variable cMix payload to the provided recipient.
+// The payload sent is based on the MessageAssembler function passed in, which
+// accepts a round ID and returns the necessary payload data.
 // Returns the round ID of the round the payload was sent or an error if it
 // fails.
 // This does not have end-to-end encryption on it and is used exclusively as
-// a send for higher order cryptographic protocols. Do not use unless
+// a send operation for higher order cryptographic protocols. Do not use unless
 // implementing a protocol on top.
 //
 //	recipient - cMix ID of the recipient.
-//	assembler - MessageAssembler function, accepting round ID and returning fingerprint
-//	format.Fingerprint, service message.Service, payload, mac []byte
+//	assembler - MessageAssembler function, accepting round ID and returning
+//	fingerprint	format.Fingerprint, service message.Service, payload, mac []byte
 //
 // Will return an error if the network is unhealthy or if it fails to send
 // (along with the reason). Blocks until successful sends or errors.
 // WARNING: Do not roll your own crypto.
-func (c *client) SendWithAssembler(recipient *id.ID, assembler MessageAssembler, cmixParams CMIXParams) (
+func (c *client) SendWithAssembler(recipient *id.ID, assembler MessageAssembler,
+	cmixParams CMIXParams) (
 	rounds.Round, ephemeral.Id, error) {
 	// Critical messaging and assembler-based message payloads are not compatible
 	if cmixParams.Critical {
-		return rounds.Round{}, ephemeral.Id{}, errors.New("Cannot send critical messages with a message assembler")
+		return rounds.Round{}, ephemeral.Id{},
+			errors.New("Cannot send critical messages with a message assembler")
 	}
 	return c.sendWithAssembler(recipient, assembler, cmixParams)
 }
 
-// sendWithAssembler wraps the passed in MessageAssembler in a messageAssembler for sendCmixHelper,
-// and sets up critical message handling where applicable.
-func (c *client) sendWithAssembler(recipient *id.ID, assembler MessageAssembler, cmixParams CMIXParams) (
+// sendWithAssembler wraps the passed in MessageAssembler in a messageAssembler
+// for sendCmixHelper, and sets up critical message handling where applicable.
+func (c *client) sendWithAssembler(recipient *id.ID, assembler MessageAssembler,
+	cmixParams CMIXParams) (
 	rounds.Round, ephemeral.Id, error) {
 	if !c.Monitor.IsHealthy() {
 		return rounds.Round{}, ephemeral.Id{}, errors.New(
@@ -156,10 +159,12 @@ func (c *client) sendWithAssembler(recipient *id.ID, assembler MessageAssembler,
 // 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, assembler messageAssembler, recipient *id.ID,
-	cmixParams CMIXParams, instance *network.Instance, grp *cyclic.Group,
-	nodes nodes.Registrar, rng *fastRNG.StreamGenerator, events event.Reporter,
-	senderId *id.ID, comms SendCmixCommsInterface, attemptTracker attempts.SendAttemptTracker) (rounds.Round, ephemeral.Id, format.Message, error) {
+func sendCmixHelper(sender gateway.Sender, assembler messageAssembler,
+	recipient *id.ID, cmixParams CMIXParams, instance *network.Instance,
+	grp *cyclic.Group, nodes nodes.Registrar, rng *fastRNG.StreamGenerator,
+	events event.Reporter, senderId *id.ID, comms SendCmixCommsInterface,
+	attemptTracker attempts.SendAttemptTracker) (
+	rounds.Round, ephemeral.Id, format.Message, error) {
 
 	if cmixParams.RoundTries == 0 {
 		return rounds.Round{}, ephemeral.Id{}, format.Message{},
diff --git a/cmix/sendCmixUtils.go b/cmix/sendCmixUtils.go
index 61a115619889746c1f3fe0f58e08f72b92c09c8f..9542af52d3bc4afdd037d99187e2bb842aaea3a7 100644
--- a/cmix/sendCmixUtils.go
+++ b/cmix/sendCmixUtils.go
@@ -191,24 +191,45 @@ func handleMissingNodeKeys(instance *network.Instance,
 	}
 }
 
-// messageListToStrings serializes a list of assembledCmixMessage into a string
-// of comma seperated recipient IDs and a string of comma seperated message
-// digests. Duplicate recipient IDs are printed once. Intended for use in
-// printing to log.
-func messageListToStrings(msgList []assembledCmixMessage) (string, string) {
-	idStrings := make([]string, 0, len(msgList))
-	idMap := make(map[id.ID]bool, len(msgList))
+// messageListToDigestStrings serializes a list of assembledCmixMessage into a
+// string of comma seperated message digests. Duplicate recipient IDs are printed
+// once. Intended for use in printing to log.
+func messageListToDigestStrings(msgList []assembledCmixMessage) string {
 	msgDigests := make([]string, len(msgList))
 
 	for i, msg := range msgList {
-		if !idMap[*msg.Recipient] {
-			idStrings = append(idStrings, msg.Recipient.String())
-			idMap[*msg.Recipient] = true
-		}
 		msgDigests[i] = msg.Message.Digest()
 	}
 
-	return strings.Join(idStrings, ", "), strings.Join(msgDigests, ", ")
+	return strings.Join(msgDigests, ", ")
+}
+
+// messageListToDigestStrings serializes a list of recipient IDs into a string
+// of comma seperated recipient IDs. Duplicate recipient IDs are printed once.
+// Intended for use in printing to log.
+func recipientsToStrings(recipients []*id.ID) string {
+	idMap := make(map[id.ID]bool, len(recipients))
+	idStrings := make([]string, 0, len(recipients))
+
+	for _, recipient := range recipients {
+		if !idMap[*recipient] {
+			idStrings = append(idStrings, recipient.String())
+			idMap[*recipient] = true
+		}
+	}
+
+	return strings.Join(idStrings, ", ")
+}
+
+// recipientsFromTargetedMessage extracts the list of recipients from a
+// list of TargetedCmixMessage.
+func recipientsFromTargetedMessage(msgs []TargetedCmixMessage) []*id.ID {
+	idStrings := make([]*id.ID, len(msgs))
+	for i, msg := range msgs {
+		idStrings[i] = msg.Recipient
+	}
+
+	return idStrings
 }
 
 // messagesToDigestString serializes a list of cMix messages into a string of
diff --git a/cmix/sendManyCmix.go b/cmix/sendManyCmix.go
index 9c3e687dbc038f32306e3a4b3584f6dab1bfc0f0..0b2fc3dac65824ebd65668ce774f734b5df2272a 100644
--- a/cmix/sendManyCmix.go
+++ b/cmix/sendManyCmix.go
@@ -53,47 +53,95 @@ type TargetedCmixMessage struct {
 // implementing a protocol on top.
 // Due to sending multiple payloads, this leaks more metadata than a
 // standard cMix send and should be in general avoided.
-//   recipient - cMix ID of the recipient.
-//   fingerprint - Key Fingerprint. 256-bit field to store a 255-bit
-//      fingerprint, highest order bit must be 0 (panic otherwise). If your
-//      system does not use key fingerprints, this must be random bits.
-//   service - Reception Service. The backup way for a client to identify
-//      messages on receipt via trial hashing and to identify notifications.
-//      If unused, use message.GetRandomService to fill the field with
-//      random data.
-//   payload - Contents of the message. Cannot exceed the payload size for a
-//      cMix message (panic otherwise).
-//   mac - 256-bit field to store a 255-bit mac, highest order bit must be 0
-//      (panic otherwise). If used, fill with random bits.
+//
+//	recipient - cMix ID of the recipient.
+//	fingerprint - Key Fingerprint. 256-bit field to store a 255-bit
+//	   fingerprint, highest order bit must be 0 (panic otherwise). If your
+//	   system does not use key fingerprints, this must be random bits.
+//	service - Reception Service. The backup way for a client to identify
+//	   messages on receipt via trial hashing and to identify notifications.
+//	   If unused, use message.GetRandomService to fill the field with
+//	   random data.
+//	payload - Contents of the message. Cannot exceed the payload size for a
+//	   cMix message (panic otherwise).
+//	mac - 256-bit field to store a 255-bit mac, highest order bit must be 0
+//	   (panic otherwise). If used, fill with random bits.
+//
 // Will return an error if the network is unhealthy or if it fails to send
 // (along with the reason). Blocks until successful send or err.
 // WARNING: Do not roll your own crypto
 func (c *client) SendMany(messages []TargetedCmixMessage,
-	p CMIXParams) (rounds.Round, []ephemeral.Id, error) {
+	params CMIXParams) (rounds.Round, []ephemeral.Id, error) {
 	if !c.Monitor.IsHealthy() {
 		return rounds.Round{}, []ephemeral.Id{}, errors.New(
 			"Cannot send cMix message when the network is not healthy")
 	}
 
-	acms := make([]assembledCmixMessage, len(messages))
-	for i := range messages {
-		msg := format.NewMessage(c.session.GetCmixGroup().GetP().ByteLen())
-		msg.SetKeyFP(messages[i].Fingerprint)
-		msg.SetContents(messages[i].Payload)
-		msg.SetMac(messages[i].Mac)
-		msg.SetSIH(messages[i].Service.Hash(msg.GetContents()))
-
-		acms[i] = assembledCmixMessage{
-			Recipient: messages[i].Recipient,
-			Message:   msg,
+	recipients := recipientsFromTargetedMessage(messages)
+	assembler := func(rid id.Round) ([]TargetedCmixMessage, error) {
+		return messages, nil
+	}
+
+	return c.sendManyWithAssembler(recipients, assembler, params)
+}
+
+// SendManyWithAssembler sends variable cMix payloads to the provided recipients.
+// The payloads sent are based on the ManyMessageAssembler function passed in,
+// which accepts a round ID and returns the necessary payload data.
+// Returns the round IDs of the rounds the payloads were sent or an error if it
+// fails.
+// This does not have end-to-end encryption on it and is used exclusively as
+// a send operation for higher order cryptographic protocols. Do not use unless
+// implementing a protocol on top.
+//
+//	recipients - cMix IDs of the recipients.
+//	assembler - ManyMessageAssembler function, accepting round ID and returning
+//	            a list of TargetedCmixMessage.
+//
+// Will return an error if the network is unhealthy or if it fails to send
+// (along with the reason). Blocks until successful sends or errors.
+// WARNING: Do not roll your own crypto.
+func (c *client) SendManyWithAssembler(recipients []*id.ID,
+	assembler ManyMessageAssembler, params CMIXParams) (
+	rounds.Round, []ephemeral.Id, error) {
+	return c.sendManyWithAssembler(recipients, assembler, params)
+}
+
+// sendManyWithAssembler wraps the passed in ManyMessageAssembler in a
+// manyMessageAssembler for sendManyCmixHelper.
+func (c *client) sendManyWithAssembler(recipients []*id.ID,
+	assembler ManyMessageAssembler, params CMIXParams) (rounds.Round,
+	[]ephemeral.Id, error) {
+
+	assemblerFunc := func(rid id.Round) ([]assembledCmixMessage, error) {
+		messages, err := assembler(rid)
+		if err != nil {
+			return nil, err
+		}
+
+		acms := make([]assembledCmixMessage, len(messages))
+		for i := range messages {
+			msg := format.NewMessage(c.session.GetCmixGroup().GetP().ByteLen())
+			msg.SetKeyFP(messages[i].Fingerprint)
+			msg.SetContents(messages[i].Payload)
+			msg.SetMac(messages[i].Mac)
+			msg.SetSIH(messages[i].Service.Hash(msg.GetContents()))
+
+			acms[i] = assembledCmixMessage{
+				Recipient: messages[i].Recipient,
+				Message:   msg,
+			}
 		}
+		return acms, nil
 	}
 
-	return sendManyCmixHelper(c.Sender, acms, p,
+	return sendManyCmixHelper(c.Sender, assemblerFunc, recipients, params,
 		c.instance, c.session.GetCmixGroup(), c.Registrar, c.rng, c.events,
 		c.session.GetTransmissionID(), c.comms, c.attemptTracker)
 }
 
+// assembledCmixMessage is a message structure containing the ready-to-send
+// Message (format.Message) and the Recipient that the message is intended.
 type assembledCmixMessage struct {
 	Recipient *id.ID
 	Message   format.Message
@@ -110,9 +158,9 @@ type assembledCmixMessage struct {
 // 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 sendManyCmixHelper(sender gateway.Sender, msgs []assembledCmixMessage,
-	param CMIXParams, instance *network.Instance, grp *cyclic.Group,
-	registrar nodes.Registrar, rng *fastRNG.StreamGenerator,
+func sendManyCmixHelper(sender gateway.Sender, assembler manyMessageAssembler,
+	recipients []*id.ID, param CMIXParams, instance *network.Instance,
+	grp *cyclic.Group, registrar nodes.Registrar, rng *fastRNG.StreamGenerator,
 	events event.Reporter, senderId *id.ID, comms SendCmixCommsInterface,
 	attemptTracker attempts.SendAttemptTracker) (
 	rounds.Round, []ephemeral.Id, error) {
@@ -127,20 +175,13 @@ func sendManyCmixHelper(sender gateway.Sender, msgs []assembledCmixMessage,
 
 	maxTimeout := sender.GetHostParams().SendTimeout
 
-	recipientString, msgDigests := messageListToStrings(msgs)
-
-	jww.INFO.Printf("[SendMany-%s] Looking for round to send cMix "+
-		"messages to [%s] (msgDigest: %s)", param.DebugTag, recipientString,
-		msgDigests)
-
 	stream := rng.GetStream()
 	defer stream.Close()
 
-	// flip leading bits randomly to thwart a tagging attack.
-	// See SetGroupBits for more info
-	for i := range msgs {
-		cmix.SetGroupBits(msgs[i].Message, grp, stream)
-	}
+	recipientsStr := recipientsToStrings(recipients)
+
+	jww.INFO.Printf("[SendMany-%s] Looking for round to send cMix "+
+		"messages to [%s]", param.DebugTag, recipientsStr)
 
 	numAttempts := 0
 	if !param.Probe {
@@ -149,17 +190,17 @@ func sendManyCmixHelper(sender gateway.Sender, msgs []assembledCmixMessage,
 			numAttempts = optimalAttempts
 			jww.INFO.Printf("[SendMany-%s] Looking for round to send cMix "+
 				"messages to %s, sending non probe with %d optimalAttempts",
-				param.DebugTag, recipientString, numAttempts)
+				param.DebugTag, recipientsStr, numAttempts)
 		} else {
 			numAttempts = 4
 			jww.INFO.Printf("[SendMany-%s] Looking for round to send cMix "+
 				"messages to %s, sending non probe with %d non optimalAttempts, "+
-				"insufficient data", param.DebugTag, recipientString, numAttempts)
+				"insufficient data", param.DebugTag, recipientsStr, numAttempts)
 		}
 	} else {
 		jww.INFO.Printf("[SendMany-%s] Looking for round to send cMix messages "+
 			"to %s, sending probe with %d Attempts, insufficient data",
-			param.DebugTag, recipientString, numAttempts)
+			param.DebugTag, recipientsStr, numAttempts)
 		defer attemptTracker.SubmitProbeAttempt(numAttempts)
 	}
 
@@ -169,16 +210,16 @@ func sendManyCmixHelper(sender gateway.Sender, msgs []assembledCmixMessage,
 
 		if elapsed > param.Timeout {
 			jww.INFO.Printf("[SendMany-%s] No rounds to send to %s "+
-				"(msgDigest: %s) were found before timeout %s", param.DebugTag,
-				recipientString, msgDigests, param.Timeout)
+				"were found before timeout %s", param.DebugTag,
+				recipientsStr, param.Timeout)
 			return rounds.Round{}, []ephemeral.Id{},
 				errors.New("sending cMix message timed out")
 		}
 
 		if numRoundTries > 0 {
 			jww.INFO.Printf("[SendMany-%s] Attempt %d to find round to "+
-				"send message to %s (msgDigest: %s)", param.DebugTag,
-				numRoundTries+1, recipientString, msgDigests)
+				"send message to %s", param.DebugTag,
+				numRoundTries+1, recipientsStr)
 		}
 
 		remainingTime := param.Timeout - elapsed
@@ -190,6 +231,12 @@ func sendManyCmixHelper(sender gateway.Sender, msgs []assembledCmixMessage,
 			continue
 		}
 
+		msgs, err := assembler(id.Round(bestRound.ID))
+		if err != nil {
+			jww.ERROR.Printf("Failed to compile messages: %+v", err)
+			return rounds.Round{}, []ephemeral.Id{}, err
+		}
+
 		// Determine whether the selected round contains any nodes that are
 		// blacklisted by the params.Network object
 		containsBlacklisted := false
@@ -209,9 +256,16 @@ func sendManyCmixHelper(sender gateway.Sender, msgs []assembledCmixMessage,
 			continue
 		}
 
+		// flip leading bits randomly to thwart a tagging attack.
+		// See SetGroupBits for more info
+		for i := range msgs {
+			cmix.SetGroupBits(msgs[i].Message, grp, stream)
+		}
+
 		// Retrieve host and key information from round
+		msgDigests := messageListToDigestStrings(msgs)
 		firstGateway, roundKeys, err := processRound(
-			registrar, bestRound, recipientString, msgDigests)
+			registrar, bestRound, recipientsStr, msgDigests)
 		if err != nil {
 			jww.INFO.Printf("[SendMany-%s] Error processing round: %v",
 				param.DebugTag, err)
@@ -247,7 +301,7 @@ func sendManyCmixHelper(sender gateway.Sender, msgs []assembledCmixMessage,
 
 		jww.INFO.Printf("[SendMany-%s]Sending to EphIDs [%s] (%s) on round %d, "+
 			"(msgDigest: %s, ecrMsgDigest: %s) via gateway %s", param.DebugTag,
-			ephemeralIDsString, recipientString, bestRound.ID, msgDigests,
+			ephemeralIDsString, recipientsStr, bestRound.ID, msgDigests,
 			encMsgsDigest, firstGateway)
 
 		// Wrap slots in the proper message type
@@ -270,7 +324,7 @@ func sendManyCmixHelper(sender gateway.Sender, msgs []assembledCmixMessage,
 				host, wrappedMessage, timeout)
 			if err != nil {
 				err := handlePutMessageError(firstGateway, registrar,
-					recipientString, bestRound, err)
+					recipientsStr, bestRound, err)
 				return result, errors.WithMessagef(err,
 					"SendMany %s (via %s): %s",
 					target, host, unrecoverableError)
@@ -292,7 +346,7 @@ func sendManyCmixHelper(sender gateway.Sender, msgs []assembledCmixMessage,
 				jww.ERROR.Printf("[SendMany-%s] SendMany failed to "+
 					"send to EphIDs [%s] (sources: %s) on round %d, trying "+
 					"a new round %+v", param.DebugTag, ephemeralIDsString,
-					recipientString, bestRound.ID, err)
+					recipientsStr, bestRound.ID, err)
 				jww.INFO.Printf("[SendMany-%s] Error received, "+
 					"continuing: %v", param.DebugTag, err)
 				continue
@@ -308,7 +362,7 @@ func sendManyCmixHelper(sender gateway.Sender, msgs []assembledCmixMessage,
 		if gwSlotResp.Accepted {
 			m := fmt.Sprintf("[SendMany-%s] Successfully sent to EphIDs "+
 				"%s (sources: [%s]) in round %d (msgDigest: %s)",
-				param.DebugTag, ephemeralIDsString, recipientString,
+				param.DebugTag, ephemeralIDsString, recipientsStr,
 				bestRound.ID, msgDigests)
 			jww.INFO.Print(m)
 			events.Report(1, "MessageSendMany", "Metric", m)
@@ -317,7 +371,7 @@ func sendManyCmixHelper(sender gateway.Sender, msgs []assembledCmixMessage,
 			jww.FATAL.Panicf("[SendMany-%s] Gateway %s returned no "+
 				"error, but failed to accept message when sending to EphIDs "+
 				"[%s] (%s) on round %d", param.DebugTag, firstGateway,
-				ephemeralIDsString, recipientString, bestRound.ID)
+				ephemeralIDsString, recipientsStr, bestRound.ID)
 		}
 	}
 
diff --git a/connect/utils_test.go b/connect/utils_test.go
index 14cce3a48f5a72a6e6392bfbd55a0663523d7398..aa507deccf371582327d2d130d721676fec0c393 100644
--- a/connect/utils_test.go
+++ b/connect/utils_test.go
@@ -173,8 +173,10 @@ func (m *mockCmix) SendWithAssembler(recipient *id.ID, assembler cmix.MessageAss
 	cmixParams cmix.CMIXParams) (rounds.Round, ephemeral.Id, error) {
 	return rounds.Round{}, ephemeral.Id{}, nil
 }
-
-func (m *mockCmix) SendMany([]cmix.TargetedCmixMessage, cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) {
+func (m *mockCmix) SendMany(messages []cmix.TargetedCmixMessage, params cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) {
+	return rounds.Round{}, []ephemeral.Id{}, nil
+}
+func (m *mockCmix) SendManyWithAssembler(recipients []*id.ID, assembler cmix.ManyMessageAssembler, params cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) {
 	return rounds.Round{}, []ephemeral.Id{}, nil
 }
 func (m *mockCmix) AddIdentity(*id.ID, time.Time, bool)                       {}
diff --git a/dummy/mockCmix_test.go b/dummy/mockCmix_test.go
index eac9913f2fc0966f3556fd3c7d85a1699049471c..a7042bc087e996d3b26906b27b001559814419c1 100644
--- a/dummy/mockCmix_test.go
+++ b/dummy/mockCmix_test.go
@@ -86,7 +86,12 @@ func (m mockCmix) GetMaxMessageLength() int {
 	return 100
 }
 
-func (m *mockCmix) SendMany(messages []cmix.TargetedCmixMessage, p cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) {
+func (m *mockCmix) SendMany(messages []cmix.TargetedCmixMessage, params cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) {
+	//TODO implement me
+	panic("implement me")
+}
+
+func (m *mockCmix) SendManyWithAssembler(recipients []*id.ID, assembler cmix.ManyMessageAssembler, params cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) {
 	//TODO implement me
 	panic("implement me")
 }
diff --git a/e2e/fpGenerator_test.go b/e2e/fpGenerator_test.go
index f5f85a66c57f5400f819cb43c08b7a11b96f6b2a..4d69dd69f353c4d51b8c180b04a48c26d1f772a1 100644
--- a/e2e/fpGenerator_test.go
+++ b/e2e/fpGenerator_test.go
@@ -130,7 +130,10 @@ func (m *mockFpgCmix) SendWithAssembler(recipient *id.ID, assembler cmix.Message
 	cmixParams cmix.CMIXParams) (rounds.Round, ephemeral.Id, error) {
 	return rounds.Round{}, ephemeral.Id{}, nil
 }
-func (m *mockFpgCmix) SendMany([]cmix.TargetedCmixMessage, cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) {
+func (m *mockFpgCmix) SendMany(messages []cmix.TargetedCmixMessage, params cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) {
+	return rounds.Round{}, nil, nil
+}
+func (m *mockFpgCmix) SendManyWithAssembler(recipients []*id.ID, assembler cmix.ManyMessageAssembler, params cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) {
 	return rounds.Round{}, nil, nil
 }
 func (m *mockFpgCmix) AddIdentity(*id.ID, time.Time, bool) {}
diff --git a/e2e/rekey/utils_test.go b/e2e/rekey/utils_test.go
index 1aeb2455306145cbf24257d6ebac2517f23a6acf..ca8ccef0816ef93de512f70df33576601c05ee03 100644
--- a/e2e/rekey/utils_test.go
+++ b/e2e/rekey/utils_test.go
@@ -250,8 +250,11 @@ func (m *mockNetManager) SendWithAssembler(recipient *id.ID, assembler cmix.Mess
 	return rounds.Round{}, ephemeral.Id{}, nil
 }
 
-func (m *mockNetManager) SendMany(messages []cmix.TargetedCmixMessage, p cmix.CMIXParams) (
-	rounds.Round, []ephemeral.Id, error) {
+func (m *mockNetManager) SendMany(messages []cmix.TargetedCmixMessage, params cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) {
+	return rounds.Round{}, nil, nil
+}
+
+func (m *mockNetManager) SendManyWithAssembler(recipients []*id.ID, assembler cmix.ManyMessageAssembler, params cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) {
 	return rounds.Round{}, nil, nil
 }
 
diff --git a/e2e/utils_test.go b/e2e/utils_test.go
index 737617f9ace539941dbd244ef21bc15f2a41fc3a..1afd01b554a66e29e0142a5211be41f9f9ec7372 100644
--- a/e2e/utils_test.go
+++ b/e2e/utils_test.go
@@ -215,8 +215,10 @@ func (m *mockCmix) SendWithAssembler(recipient *id.ID, assembler cmix.MessageAss
 	cmixParams cmix.CMIXParams) (rounds.Round, ephemeral.Id, error) {
 	panic("implement me")
 }
-
-func (m *mockCmix) SendMany([]cmix.TargetedCmixMessage, cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) {
+func (m *mockCmix) SendMany(messages []cmix.TargetedCmixMessage, params cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) {
+	return rounds.Round{}, nil, nil
+}
+func (m *mockCmix) SendManyWithAssembler(recipients []*id.ID, assembler cmix.ManyMessageAssembler, params cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) {
 	return rounds.Round{}, nil, nil
 }
 func (m *mockCmix) AddIdentity(*id.ID, time.Time, bool) {}
diff --git a/fileTransfer/connect/utils_test.go b/fileTransfer/connect/utils_test.go
index 222bd58fe1d2055b924cd03a8a284b2ef2ef747a..5ad7afff04191a8e82b0c8b2ac815e708bc2514e 100644
--- a/fileTransfer/connect/utils_test.go
+++ b/fileTransfer/connect/utils_test.go
@@ -123,9 +123,7 @@ func (m *mockCmix) Send(*id.ID, format.Fingerprint, message.Service, []byte,
 	[]byte, cmix.CMIXParams) (rounds.Round, ephemeral.Id, error) {
 	panic("implement me")
 }
-
-func (m *mockCmix) SendMany(messages []cmix.TargetedCmixMessage,
-	_ cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) {
+func (m *mockCmix) SendMany(messages []cmix.TargetedCmixMessage, params cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) {
 	m.handler.Lock()
 	for _, targetedMsg := range messages {
 		msg := format.NewMessage(m.numPrimeBytes)
@@ -140,6 +138,10 @@ func (m *mockCmix) SendMany(messages []cmix.TargetedCmixMessage,
 	return rounds.Round{ID: 42}, []ephemeral.Id{}, nil
 }
 
+func (m *mockCmix) SendManyWithAssembler(recipients []*id.ID, assembler cmix.ManyMessageAssembler, params cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) {
+	//TODO implement me
+	panic("implement me")
+}
 func (m *mockCmix) SendWithAssembler(*id.ID, cmix.MessageAssembler,
 	cmix.CMIXParams) (rounds.Round, ephemeral.Id, error) {
 	panic("implement me")
diff --git a/fileTransfer/e2e/utils_test.go b/fileTransfer/e2e/utils_test.go
index bb8228dd6563fe69e3ed03e45f05d7b6eaadde77..0e71b45232060feb1d1ea694793f41f0730e574a 100644
--- a/fileTransfer/e2e/utils_test.go
+++ b/fileTransfer/e2e/utils_test.go
@@ -126,8 +126,7 @@ func (m *mockCmix) Send(*id.ID, format.Fingerprint, message.Service, []byte,
 	panic("implement me")
 }
 
-func (m *mockCmix) SendMany(messages []cmix.TargetedCmixMessage,
-	_ cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) {
+func (m *mockCmix) SendMany(messages []cmix.TargetedCmixMessage, params cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) {
 	m.handler.Lock()
 	for _, targetedMsg := range messages {
 		msg := format.NewMessage(m.numPrimeBytes)
@@ -142,6 +141,11 @@ func (m *mockCmix) SendMany(messages []cmix.TargetedCmixMessage,
 	return rounds.Round{ID: 42}, []ephemeral.Id{}, nil
 }
 
+func (m *mockCmix) SendManyWithAssembler(recipients []*id.ID, assembler cmix.ManyMessageAssembler, params cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) {
+	//TODO implement me
+	panic("implement me")
+}
+
 func (m *mockCmix) SendWithAssembler(*id.ID, cmix.MessageAssembler,
 	cmix.CMIXParams) (rounds.Round, ephemeral.Id, error) {
 	panic("implement me")
diff --git a/fileTransfer/groupChat/utils_test.go b/fileTransfer/groupChat/utils_test.go
index 497029a3f1b31322accbef6b31e12199edd4d64a..055a45e6cb5a8a6c28e8aeacd94e07d780094547 100644
--- a/fileTransfer/groupChat/utils_test.go
+++ b/fileTransfer/groupChat/utils_test.go
@@ -121,8 +121,7 @@ func (m *mockCmix) Send(*id.ID, format.Fingerprint, message.Service, []byte,
 	panic("implement me")
 }
 
-func (m *mockCmix) SendMany(messages []cmix.TargetedCmixMessage,
-	_ cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) {
+func (m *mockCmix) SendMany(messages []cmix.TargetedCmixMessage, params cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) {
 	m.handler.Lock()
 	for _, targetedMsg := range messages {
 		msg := format.NewMessage(m.numPrimeBytes)
@@ -137,6 +136,11 @@ func (m *mockCmix) SendMany(messages []cmix.TargetedCmixMessage,
 	return rounds.Round{ID: 42}, []ephemeral.Id{}, nil
 }
 
+func (m *mockCmix) SendManyWithAssembler(recipients []*id.ID, assembler cmix.ManyMessageAssembler, params cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) {
+	//TODO implement me
+	panic("implement me")
+}
+
 func (m *mockCmix) SendWithAssembler(*id.ID, cmix.MessageAssembler,
 	cmix.CMIXParams) (rounds.Round, ephemeral.Id, error) {
 	panic("implement me")
@@ -224,9 +228,10 @@ func (m *mockCmix) ChangeNumberOfNodeRegistrations(toRun int, timeout time.Durat
 	return nil
 }
 
-// //////////////////////////////////////////////////////////////////////////////
-// Mock Group Chat Manager                                                    //
-// //////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// Mock Group Chat Manager                                                   //
+///////////////////////////////////////////////////////////////////////////////
+
 type mockGcHandler struct {
 	services map[string]groupChat.Processor
 	sync.Mutex
diff --git a/fileTransfer/manager.go b/fileTransfer/manager.go
index f4f72824921afec1c2483f3e829862008baf00d9..dc65222b3730a23e0364ef77510925b32d505886 100644
--- a/fileTransfer/manager.go
+++ b/fileTransfer/manager.go
@@ -146,8 +146,8 @@ type FtE2e interface {
 // transfer manager for easier testing.
 type Cmix interface {
 	GetMaxMessageLength() int
-	SendMany(messages []cmix.TargetedCmixMessage, p cmix.CMIXParams) (rounds.Round,
-		[]ephemeral.Id, error)
+	SendMany(messages []cmix.TargetedCmixMessage,
+		p cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error)
 	AddFingerprint(identity *id.ID, fingerprint format.Fingerprint,
 		mp message.Processor) error
 	DeleteFingerprint(identity *id.ID, fingerprint format.Fingerprint)
diff --git a/fileTransfer/send.go b/fileTransfer/send.go
index c3504c2ca53dc824a0be524fe8b453ba271c229f..0330688e5e45219132e2caa96e6a82a0c69a573d 100644
--- a/fileTransfer/send.go
+++ b/fileTransfer/send.go
@@ -139,7 +139,6 @@ func (m *manager) sendCmix(packet []store.Part) {
 		}
 
 		validParts = append(validParts, p)
-
 		messages = append(messages, cmix.TargetedCmixMessage{
 			Recipient:   p.Recipient(),
 			Payload:     encryptedPart,
diff --git a/fileTransfer/utils_test.go b/fileTransfer/utils_test.go
index 92bcc8288bb51c0f7ed2172d885054635e0eafc5..1ccdb1792f16c0c9c7737bf1d135f7b71c4aedae 100644
--- a/fileTransfer/utils_test.go
+++ b/fileTransfer/utils_test.go
@@ -175,8 +175,7 @@ func (m *mockCmix) Send(*id.ID, format.Fingerprint, message.Service, []byte,
 	panic("implement me")
 }
 
-func (m *mockCmix) SendMany(messages []cmix.TargetedCmixMessage,
-	_ cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) {
+func (m *mockCmix) SendMany(messages []cmix.TargetedCmixMessage, params cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) {
 	m.handler.Lock()
 	defer m.handler.Unlock()
 	round := m.round
@@ -193,6 +192,10 @@ func (m *mockCmix) SendMany(messages []cmix.TargetedCmixMessage,
 	return rounds.Round{ID: round}, []ephemeral.Id{}, nil
 }
 
+func (m *mockCmix) SendManyWithAssembler(recipients []*id.ID, assembler cmix.ManyMessageAssembler, params cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) {
+	//TODO implement me
+	panic("implement me")
+}
 func (m *mockCmix) SendWithAssembler(*id.ID, cmix.MessageAssembler,
 	cmix.CMIXParams) (rounds.Round, ephemeral.Id, error) {
 	panic("implement me")
diff --git a/groupChat/interface.go b/groupChat/interface.go
index 391e60954034dd9015355024e03d831e934548d7..563efdc08583cb7051ecbc52d6dcec58582635ed 100644
--- a/groupChat/interface.go
+++ b/groupChat/interface.go
@@ -114,8 +114,8 @@ type groupE2e interface {
 // groupCmix is a subset of the cmix.Client interface containing only the
 // methods needed by GroupChat
 type groupCmix interface {
-	SendMany(messages []cmix.TargetedCmixMessage, p cmix.CMIXParams) (
-		rounds.Round, []ephemeral.Id, error)
+	SendMany(messages []cmix.TargetedCmixMessage,
+		p cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error)
 	AddService(
 		clientID *id.ID, newService message.Service, response message.Processor)
 	DeleteService(
diff --git a/groupChat/networkManager_test.go b/groupChat/networkManager_test.go
index f413dd5f498f5e6bd41952bfcfaea7161844d2d5..5ea299aafecbb0cb4bda8808c8139eebdf185fb6 100644
--- a/groupChat/networkManager_test.go
+++ b/groupChat/networkManager_test.go
@@ -49,7 +49,7 @@ func newTestNetworkManager(sendErr int) cmix.Client {
 	}
 }
 
-func (tnm *testNetworkManager) SendMany(messages []cmix.TargetedCmixMessage, _ cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) {
+func (tnm *testNetworkManager) SendMany(messages []cmix.TargetedCmixMessage, params cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) {
 	if tnm.sendErr == 1 {
 		return rounds.Round{}, nil, errors.New("SendManyCMIX error")
 	}
@@ -71,6 +71,9 @@ func (tnm *testNetworkManager) SendMany(messages []cmix.TargetedCmixMessage, _ c
 	return rounds.Round{}, nil, nil
 }
 
+func (tnm *testNetworkManager) SendManyWithAssembler(recipients []*id.ID, assembler cmix.ManyMessageAssembler, params cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) {
+	return rounds.Round{}, nil, nil
+}
 func (*testNetworkManager) AddService(*id.ID, message.Service, message.Processor) {}
 func (*testNetworkManager) IncreaseParallelNodeRegistration(int) func() (stoppable.Stoppable, error) {
 	return nil
diff --git a/groupChat/send.go b/groupChat/send.go
index 0491081ff8ff09017f9646b031765d6f6f3b2909..1894ad3305c46c35fa33b02eeed19d42fc25fc39 100644
--- a/groupChat/send.go
+++ b/groupChat/send.go
@@ -74,7 +74,8 @@ func (m *manager) Send(groupID *id.ID, tag string, message []byte) (
 	rid, _, err := m.getCMix().SendMany(groupMessages, param)
 	if err != nil {
 		return rounds.Round{}, time.Time{}, group.MessageID{},
-			errors.Errorf(sendManyCmixErr, m.getReceptionIdentity().ID, g.Name, g.ID, err)
+			errors.Errorf(sendManyCmixErr, m.getReceptionIdentity().ID, g.Name,
+				g.ID, err)
 	}
 
 	jww.DEBUG.Printf("[GC] Sent message to %d members in group %s at %s.",
@@ -86,8 +87,6 @@ func (m *manager) Send(groupID *id.ID, tag string, message []byte) (
 func (m *manager) newMessages(g gs.Group, tag string, msg []byte,
 	timestamp time.Time) ([]cmix.TargetedCmixMessage, group.MessageID, error) {
 
-	// Create list of cMix messages
-	messages := make([]cmix.TargetedCmixMessage, 0, len(g.Members))
 	rng := m.getRng().GetStream()
 	defer rng.Close()
 
@@ -117,6 +116,7 @@ func (m *manager) newMessages(g gs.Group, tag string, msg []byte,
 		m.getReceptionIdentity().ID, msg)
 
 	// Create cMix messages
+	messages := make([]cmix.TargetedCmixMessage, 0, len(g.Members))
 	for _, member := range g.Members {
 		// Do not send to the sender
 		if m.getReceptionIdentity().ID.Cmp(member.ID) {
@@ -124,8 +124,8 @@ func (m *manager) newMessages(g gs.Group, tag string, msg []byte,
 		}
 
 		// Add cMix message to list
-		cMixMsg, err := newCmixMsg(g, tag, timestamp, member, rng, maxCmixMessageLength,
-			internalMessagePayload)
+		cMixMsg, err := newCmixMsg(g, tag, timestamp, member, rng,
+			maxCmixMessageLength, internalMessagePayload)
 		if err != nil {
 			return nil, group.MessageID{}, err
 		}
diff --git a/ud/networkManager_test.go b/ud/networkManager_test.go
index dc7f811cb120915a2b19fde9295cdfccf1d4cdbc..97a5b165299ea8544dffb2e9767bebae848cad72 100644
--- a/ud/networkManager_test.go
+++ b/ud/networkManager_test.go
@@ -180,7 +180,12 @@ func (tnm *testNetworkManager) SendToAny(sendFunc func(host *connect.Host) (inte
 	panic("implement me")
 }
 
-func (tnm *testNetworkManager) SendMany(messages []cmix.TargetedCmixMessage, p cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) {
+func (tnm *testNetworkManager) SendMany(messages []cmix.TargetedCmixMessage, params cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) {
+	//TODO implement me
+	panic("implement me")
+}
+
+func (tnm *testNetworkManager) SendManyWithAssembler(recipients []*id.ID, assembler cmix.ManyMessageAssembler, params cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) {
 	//TODO implement me
 	panic("implement me")
 }
diff --git a/xxdk/utilsInterfaces_test.go b/xxdk/utilsInterfaces_test.go
index efff3fd1699af7adf8ec8e20ff8d8600ae3098a3..0320ab726f764b22f261c7fc18ee92f103b4198a 100644
--- a/xxdk/utilsInterfaces_test.go
+++ b/xxdk/utilsInterfaces_test.go
@@ -125,9 +125,10 @@ func (t *testNetworkManagerGeneric) SendWithAssembler(recipient *id.ID, assemble
 
 	return rounds.Round{}, ephemeral.Id{}, nil
 }
-
-func (t *testNetworkManagerGeneric) SendMany(messages []cmix.TargetedCmixMessage,
-	p cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) {
+func (t *testNetworkManagerGeneric) SendMany(messages []cmix.TargetedCmixMessage, params cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) {
+	return rounds.Round{}, []ephemeral.Id{}, nil
+}
+func (t *testNetworkManagerGeneric) SendManyWithAssembler(recipients []*id.ID, assembler cmix.ManyMessageAssembler, params cmix.CMIXParams) (rounds.Round, []ephemeral.Id, error) {
 	return rounds.Round{}, []ephemeral.Id{}, nil
 }
 func (t *testNetworkManagerGeneric) GetInstance() *network.Instance {