diff --git a/README.md b/README.md
index 62b1ed0de9a3a23929243db3299027af71793ee2..85caa9719203f12bf8bfbcb7d9e22b02cf37102f 100644
--- a/README.md
+++ b/README.md
@@ -4,12 +4,12 @@
 [![coverage report](https://gitlab.com/elixxir/client/badges/master/coverage.svg)](https://gitlab.com/elixxir/client/commits/master)
 
 
-The client is a library and related command-line tool 
+The client is a library and related command-line tool
 that facilitates making full-featured xx clients for all platforms. It interfaces with the cMix system, enabling access
 to all xx network messaging features, including end-to-end encryption and metadata protection.
 
 This repository contains everything necessary to implement all of the
-xx network messaging features. It also contains features to extend the base 
+xx network messaging features. It also contains features to extend the base
 messaging protocols.
 
 The command-line tool accompanying the client library can be built for any platform supported by
@@ -27,7 +27,7 @@ The client is open-source software released under the simplified BSD License.
 ## Command Line Usage
 
 The command-line tool is intended for testing xx network functionality and not
-for regular user use. 
+for regular user use.
 
 These instructions assume that you have [Go 1.17.X installed](https://go.dev/doc/install), and GCC installed for Cgo (such as `build-essential` on Debian or Ubuntu).
 
@@ -51,12 +51,26 @@ GOOS=darwin GOARCH=amd64 CGO_ENABLED=0 go build -ldflags '-w -s' -o release/clie
 
 #### Fetching an NDF
 
-All actions performed with the client require a current [NDF](https://xxdk-dev.xx.network/technical-glossary#network-definition-file-ndf). The NDF is downloadable from the command line or [via an access point](https://xxdk-dev.xx.network/quick-reference#func-downloadandverifysignedndfwithurl) in the Client API.
+All actions performed with the client require a
+current [NDF](https://xxdk-dev.xx.network/technical-glossary#network-definition-file-ndf). The NDF is downloadable from
+the command line
+or [via an access point](https://xxdk-dev.xx.network/quick-reference#func-downloadandverifysignedndfwithurl) in the
+Client API.
 
-Use the `getndf` command to fetch the NDF via the command  line. `getndf` enables command-line users to poll the NDF from a network gateway without any pre-established client connection: 
+Use the `getndf` command to fetch the NDF via the command line. `getndf` enables command-line users to poll the NDF from
+a network gateway without any pre-established client connection.
+
+First, you'll want to download an SSL certificate:
+
+```
+// Assumes you are running a gateway locally
+openssl s_client -showcerts -connect localhost:8440 < /dev/null 2>&1 | openssl x509 -outform PEM > certfile.pem
+```
+
+Now you can fetch the NDF:
 
 ```
-// Fetch NDF (example usage for Gateways, assumes you are running a gateway locally)
+// Example usage for Gateways, assumes you are running a gateway locally
 $ go run main.go getndf --gwhost localhost:8440 --cert certfile.pem | jq . >ndf.json
 ```
 
@@ -83,10 +97,16 @@ Sample content of `ndf.json`:
 	  .....
 ```
 
-#### Sending safe messages between 2 users
+#### Sending Safe Messages Between Two (2) Users
+
+**Note:** For information on receiving messages and troubleshooting authenticated channel requests,
+see [Receiving Messages](#receiving-messages)
+and [Confirming authenticated channel requests](#confirming-authenticated-channel-requests).
 
 To send messages with end-to-end encryption, you must first establish a connection
-or [authenticated channel](https://xxdk-dev.xx.network/technical-glossary#authenticated-channel) with the other user:
+or [authenticated channel](https://xxdk-dev.xx.network/technical-glossary#authenticated-channel) with the other user.
+See below for example commands for sending or confirming authenticated channel requests, as well as for sending E2E
+messages:
 
 ```
 # Get user contact jsons for each client
@@ -102,9 +122,9 @@ Message received:
 Sending to Qm40C5hRUm7uhp5aATVWhSL6Mt+Z4JVBQrsEDvMORh4D:
 Received 1
 
-# Alternatively, to accept an authenticated channel request implicitly
-# (should be within the timeout window of requesting client, or the request will need to be resent):
-$ client --password "password" --ndf ndf.json -l client.log -s session-directory --destfile user2-contact.json" --unsafe-channel-creation --waitTimeout 200
+# Accept/Confirm an authenticated channel request implicitly
+# (should be within the timeout window of requesting client, or the request will need to be re-sent):
+$ client --password "password" --ndf ndf.json -l client.log -s session-directory --destfile user2-contact.json --unsafe-channel-creation --waitTimeout 200
 Authentication channel request from: o+QpswTmnsuZve/QRz0j0RYNWqjgx4R5pACfO00Pe0cD
 Sending to o+QpswTmnsuZve/QRz0j0RYNWqjgx4R5pACfO00Pe0cD:
 Message received:
@@ -128,7 +148,7 @@ Received 0
 * `-s`: The storage directory for client session data.
 * `--writeContact`: Output the user's contact information to this file.
 * `--destfile` is used to specify the recipient. You can also use
-  `--destid b64:...` using the user's base64 id which is printed in the logs.
+  `--destid b64:...` using the user's base64 id, which is printed in the logs.
 * `--unsafe`: Send message without encryption (necessary whenever you have not
   already established an e2e channel).
 * `--unsafe-channel-creation` Auto-create and auto-accept channel requests.
@@ -136,12 +156,12 @@ Received 0
 
 Note that the client defaults to sending to itself when a destination is not supplied.
 This is why we've used the `--unsafe` flag when creating the user contact jsons.
-However, when sending between users it is dropped in exchange for `--unsafe-channel-creation`.
+However, when sending between users, it is dropped in exchange for `--unsafe-channel-creation`.
 
-For the authenticated channel creation to be considered "safe" the user should be prompted. You can do this
-on the command line by explicitly accepting the channel creation
-when sending a request with `--send-auth-request` and/or explicitly accepting a request with
-`--accept-channel`:
+For the authenticated channel creation to be considered "safe", the user should be prompted. You can do this by
+explicitly accepting the channel creation
+when sending a request with `--send-auth-request` (while excluding the `--unsafe-channel-creation` flag) or explicitly
+accepting a request with `--accept-channel`:
 
 ```
 $ client --password user-password --ndf ndf.json -l client.log -s session-directory --destfile user-contact.json --accept-channel
@@ -151,6 +171,61 @@ Message received:
 Received 1
 ```
 
+#### Receiving Messages
+
+There is no explicit command for receiving messages. Instead, the client will attempt to fetch pending messages on each
+run.
+
+You can use the `--receiveCount` flag to limit the number of messages the client waits for before a timeout occurs:
+
+```
+$ client --password <password> --ndf <NDF JSON file> -l client.log -s <session directory> --destfile <contact JSON file> --receiveCount <integer count>
+```
+
+#### Sending Authenticated Channel Requests
+
+See [Sending Safe Messages Between Two (2) Users](#sending-safe-messages-between-two-2-users)
+
+#### Confirming Authenticated Channel Requests
+
+Setting up an authenticated channel between clients is a back-and-forth process that happens in sequence. One client
+sends a request and waits for the other to accept it.
+
+See the previous section, [Sending safe messages between 2 users](#sending-safe-messages-between-2-users), for example
+commands showing how to set up an end-to-end connection between clients before sending messages.
+
+As with received messages, there is no command for checking for authenticated channel requests; you'll be notified of
+any pending requests whenever the client is run.
+
+```
+$ ./client.win64 --password password --ndf ndf.json -l client.log -s session-directory --destfile user-contact8.json --waitTimeout 120 -m "Hi User 7, from User 8 with E2E Encryption"
+Authentication channel request from: 8zAWY69UUK/FkMBGY3ViR5MMfcp1GoKn6Y3c/64NYNYD
+Sending to yYAztmoCoAH2VIr00zPxnj/ZRvdiDdURjdDWys0KYI4D: Hi User 7, from User 8 with E2E Encryption
+Timed out!
+Received 0
+
+```
+
+##### Troubleshooting
+
+**`panic: Could not confirm authentication channel for ...`**
+
+Suppose the receiving client does not confirm the authentication channel before the requesting client reaches a
+timeout (default 120s). In that case, the request eventually terminates in
+a `panic: Could not confirm authentication channel for ...` error.
+
+Retrying the request should fix this. If necessary, you may increase the time the client waits to confirm the channel
+before timeout using the `--auth-timeout` flag (default 120s).
+
+This error will also occur with the receiving client if it received the request but failed to confirm it before the
+requesting client reached a timeout. In this case, the request needs to be resent while the other client reattempts to
+confirm the channel.
+
+**`panic: Received request not found`**
+
+You may also run into the `panic: Received request not found` error when attempting to confirm an authenticated channel
+request. This means your client has not received the request. If one has been sent, simply retrying should fix this.
+
 Full usage of client can be found with `client --help`:
 
 ```
@@ -221,9 +296,9 @@ Use "client [command] --help" for more information about a command.
 
 ## Library Overview
 
-The xx client is designed to be used as a go library (and by extension a 
-c library). 
- 
+The xx client is designed to be used as a go library (and by extension a
+c library).
+
 Support is also present for go mobile to build Android and iOS libraries. We
 bind all exported symbols from the bindings package for use on mobile
 platforms.
@@ -232,7 +307,8 @@ platforms.
 
 Clients need to perform the same actions *in the same order* as shown in
 `cmd/root.go`. Specifically, certain handlers need to be registered and
-set up before starting network threads. Additionally, you cannot perform certain actions until the network connection reaches a "healthy" state.
+set up before starting network threads. Additionally, you cannot perform certain actions until the network connection
+reaches a "healthy" state.
 
 See [main.go](https://git.xx.network/elixxir/xxdk-examples/-/blob/sample-messaging-app/sample-messaging-app/main.go) for relevant code listings on when and how to perform these actions.
 The [Getting Started](https://xxdk-dev.xx.network/getting-started) guide provides further detail.
@@ -340,7 +416,7 @@ parts of the roadmap that are intended for the client:
 * User Discovery - A bot that will allow the user to look for others on the
   network.
 * Notifications - An optional notifications system which uses firebase
-* Efficiency improvements - mechanisms for message pickup and network tracking 
+* Efficiency improvements - mechanisms for message pickup and network tracking
 * will evolve to allow tradeoffs and options for use
 
 We are also always looking at simplifying and improving the library interface.
diff --git a/cmix/gateway/hostPool.go b/cmix/gateway/hostPool.go
index 224489af202afd203c1f917ce163b901deeade3d..52b29d45f1661cb025799d993e401e2dd9108cc3 100644
--- a/cmix/gateway/hostPool.go
+++ b/cmix/gateway/hostPool.go
@@ -271,7 +271,7 @@ func newHostPool(poolParams PoolParams, rng *fastRNG.StreamGenerator,
 	return result, nil
 }
 
-// initialize initializes the HostPool with a performant set of Hosts.
+// initialize the HostPool with a performant set of Hosts.
 func (h *HostPool) initialize(startIdx uint32) error {
 	// If HostPool is full, there is no need to initialize
 	if startIdx == h.poolParams.PoolSize {
diff --git a/cmix/nodes/register.go b/cmix/nodes/register.go
index 80c85547f333df28eda9cd21b14a98ab73623d71..000b5751501b8120c35f099f3a2db59257a8fb07 100644
--- a/cmix/nodes/register.go
+++ b/cmix/nodes/register.go
@@ -95,7 +95,7 @@ func registerNodes(r *registrar, s session, stop *stoppable.Single,
 
 			// Process the result
 			if err != nil {
-				jww.ERROR.Printf("Failed to register nodes: %s", err.Error())
+				jww.ERROR.Printf("Failed to register node: %s", err.Error())
 				// If we have not reached the attempt limit for this gateway,
 				// then send it back into the channel to retry
 				if numAttempts < maxAttempts {
diff --git a/cmix/nodes/request.go b/cmix/nodes/request.go
index b75f7801cbb53ed41843a92511a2e89cfafae91f..f41b6b88e2cf476c59f8b00344cfff7101537673 100644
--- a/cmix/nodes/request.go
+++ b/cmix/nodes/request.go
@@ -64,8 +64,8 @@ func requestKey(sender gateway.Sender, comms RegisterNodeCommsInterface,
 	result, err := sender.SendToAny(func(host *connect.Host) (interface{}, error) {
 		keyResponse, err2 := comms.SendRequestClientKeyMessage(host, signedKeyReq)
 		if err2 != nil {
-			return nil, errors.WithMessage(err2,
-				"Register: Failed requesting client key from gateway")
+			return nil, errors.WithMessagef(err2,
+				"Register: Failed requesting client key from gateway %s", gatewayID.String())
 		}
 		if keyResponse.Error != "" {
 			return nil, errors.WithMessage(err2,
diff --git a/groupChat/receive.go b/groupChat/receive.go
index 56f8d56fd76cb2461b0612ee3492812596463e89..63e6f91c0c904351d2c8590d29ebb7aa9a6d98d8 100644
--- a/groupChat/receive.go
+++ b/groupChat/receive.go
@@ -9,6 +9,7 @@ package groupChat
 
 import (
 	"fmt"
+	"gitlab.com/xx_network/primitives/netTime"
 	"time"
 
 	"github.com/pkg/errors"
@@ -55,8 +56,10 @@ func (p *receptionProcessor) Process(message format.Message,
 	}
 
 	// Obtain the decryption key for the public message
+	// We use PRECOMPUTING here because all Rounds have that timestamp available to them
+	// QUEUED can be missing sometimes and cause a lot of hidden problems further down the line
 	key, err := getCryptKey(p.g.Key, pubMsg.GetSalt(), message.GetMac(),
-		pubMsg.GetPayload(), p.g.DhKeys, round.Timestamps[states.QUEUED])
+		pubMsg.GetPayload(), p.g.DhKeys, round.Timestamps[states.PRECOMPUTING])
 	if err != nil {
 		jww.ERROR.Printf(getDecryptionKeyErr, err)
 		return
@@ -125,6 +128,12 @@ func decryptMessage(g gs.Group, fingerprint format.Fingerprint,
 func getCryptKey(key group.Key, salt [group.SaltLen]byte, mac, payload []byte,
 	dhKeys gs.DhKeyList, roundTimestamp time.Time) (group.CryptKey, error) {
 
+	// If given zero time, try to guesstimate roundTimestamp as right now
+	if roundTimestamp.Equal(time.Unix(0, 0)) {
+		jww.ERROR.Printf("getCryptKey missing roundTimestamp")
+		roundTimestamp = netTime.Now()
+	}
+
 	// Compute the current epoch
 	epoch := group.ComputeEpoch(roundTimestamp)
 	for _, dhKey := range dhKeys {