diff --git a/cmd/dumpRounds.go b/cmd/dumpRounds.go
index f690f5ba1bba6fe54cab9929c6e3f1e88f50f966..88743972921640bc169fd7213122e07254af77b0 100644
--- a/cmd/dumpRounds.go
+++ b/cmd/dumpRounds.go
@@ -11,16 +11,19 @@ package cmd
 import (
 	"encoding/base64"
 	"fmt"
-	"github.com/spf13/viper"
 	"strconv"
 	"time"
 
+	"github.com/spf13/viper"
+
 	"github.com/spf13/cobra"
 	jww "github.com/spf13/jwalterweatherman"
 	"gitlab.com/elixxir/client/cmix/rounds"
+	"gitlab.com/elixxir/client/xxdk"
 	"gitlab.com/xx_network/comms/signature"
 	"gitlab.com/xx_network/crypto/signature/ec"
 	"gitlab.com/xx_network/primitives/id"
+	"gitlab.com/xx_network/primitives/ndf"
 )
 
 // dumpRoundsCmd allows the user to view network information about a specific
@@ -48,91 +51,13 @@ var dumpRoundsCmd = &cobra.Command{
 			})
 		waitUntilConnected(connected)
 
-		numRequests := len(roundIDs)
-		requestCh := make(chan bool, numRequests)
+		roundInfos := dumpRounds(roundIDs, user)
 
-		registration := user.GetStorage().GetNDF().Registration
-		ecp := registration.EllipticPubKey
-		pubkey, err := ec.LoadPublicKey(ecp)
-		if err != nil {
-			jww.FATAL.Panicf("%+v", err)
-		}
-		fmt.Printf("registration pubkey: %s\n\n", pubkey.MarshalText())
-
-		rcb := func(round rounds.Round, success bool) {
-			if !success {
-				fmt.Printf("round %v lookup failed", round.ID)
-			}
-
-			fmt.Printf("Round %v:", round.ID)
-			fmt.Printf("\n\tBatch size: %v, State: %v",
-				round.BatchSize, round.State)
-			fmt.Printf("\n\tUpdateID: %v, AddrSpaceSize: %v",
-				round.UpdateID, round.AddressSpaceSize)
-
-			fmt.Printf("\n\tTopology: ")
-			for i, nodeId := range round.Raw.Topology {
-				nidStr := base64.StdEncoding.EncodeToString(
-					nodeId)
-				fmt.Printf("\n\t\t%d\t-\t%s", i, nidStr)
-			}
-
-			fmt.Printf("\n\tTimestamps: ")
-			for state, ts := range round.Timestamps {
-				fmt.Printf("\n\t\t%v  \t-\t%v", state, ts)
-			}
-
-			fmt.Printf("\n\tErrors (%d): ", len(round.Raw.Errors))
-			for i, err := range round.Raw.Errors {
-				fmt.Printf("\n\t\t%d - %v", i, err)
-			}
-
-			fmt.Printf("\n\tClientErrors (%d): ",
-				len(round.Raw.ClientErrors))
-			for _, ce := range round.Raw.ClientErrors {
-				fmt.Printf("\n\t\t%s - %v, Src: %v",
-					base64.StdEncoding.EncodeToString(
-						ce.ClientId),
-					ce.Error,
-					base64.StdEncoding.EncodeToString(
-						ce.Source))
-			}
-
-			ri := round.Raw
-			err = signature.VerifyEddsa(ri, pubkey)
-			if err != nil {
-				fmt.Printf("\n\tECC signature failed: %v", err)
-				fmt.Printf("\n\tuse trace logging for sig details")
-			} else {
-				fmt.Printf("\n\tECC signature succeeded!\n\n")
-			}
-
-			// fmt.Printf("Round Info RAW: %v\n\n", round)
-
-			// rsapubkey, _ := rsa.LoadPublicKeyFromPem([]byte(
-			// 	registration.TlsCertificate))
-			// signature.VerifyRsa(ri, rsapubkey)
-			// if err != nil {
-			// 	fmt.Printf("RSA signature failed: %v", err)
-			// 	fmt.Printf("use trace logging for sig details")
-			// } else {
-			// 	fmt.Printf("RSA signature succeeded!")
-			// }
-
-			requestCh <- success
-		}
-
-		for i := range roundIDs {
-			rid := roundIDs[i]
-			err := user.GetCmix().LookupHistoricalRound(rid, rcb)
-			if err != nil {
-				fmt.Printf("error on %v: %v", rid, err)
-			}
-		}
+		ndf := user.GetStorage().GetNDF()
 
-		for done := 0; done < numRequests; done++ {
-			res := <-requestCh
-			fmt.Printf("request complete: %v", res)
+		for i := range roundInfos {
+			printRoundInfo(roundInfos[i])
+			printAndVerifyRoundSig(roundInfos[i], ndf)
 		}
 	},
 }
@@ -141,6 +66,101 @@ func init() {
 	rootCmd.AddCommand(dumpRoundsCmd)
 }
 
+func printRoundInfo(round rounds.Round) {
+	fmt.Printf("Round %v:", round.ID)
+	fmt.Printf("\n\tBatch size: %v, State: %v",
+		round.BatchSize, round.State)
+	fmt.Printf("\n\tUpdateID: %v, AddrSpaceSize: %v",
+		round.UpdateID, round.AddressSpaceSize)
+
+	fmt.Printf("\n\tTopology: ")
+	for i, nodeId := range round.Raw.Topology {
+		nidStr := base64.StdEncoding.EncodeToString(
+			nodeId)
+		fmt.Printf("\n\t\t%d\t-\t%s", i, nidStr)
+	}
+
+	fmt.Printf("\n\tTimestamps: ")
+	for state, ts := range round.Timestamps {
+		fmt.Printf("\n\t\t%v  \t-\t%v", state, ts)
+	}
+
+	fmt.Printf("\n\tErrors (%d): ", len(round.Raw.Errors))
+	for i, err := range round.Raw.Errors {
+		fmt.Printf("\n\t\t%d - %v", i, err)
+	}
+
+	fmt.Printf("\n\tClientErrors (%d): ",
+		len(round.Raw.ClientErrors))
+	for _, ce := range round.Raw.ClientErrors {
+		fmt.Printf("\n\t\t%s - %v, Src: %v",
+			base64.StdEncoding.EncodeToString(
+				ce.ClientId),
+			ce.Error,
+			base64.StdEncoding.EncodeToString(
+				ce.Source))
+	}
+}
+
+func printAndVerifyRoundSig(round rounds.Round, ndf *ndf.NetworkDefinition) {
+	registration := ndf.Registration
+	ecp := registration.EllipticPubKey
+	pubkey, err := ec.LoadPublicKey(ecp)
+	if err != nil {
+		jww.FATAL.Panicf("%+v", err)
+	}
+	fmt.Printf("registration pubkey: %s\n\n", pubkey.MarshalText())
+
+	ri := round.Raw
+	err = signature.VerifyEddsa(ri, pubkey)
+	if err != nil {
+		fmt.Printf("\n\tECC signature failed: %v", err)
+		fmt.Printf("\n\tuse trace logging for sig details")
+	} else {
+		fmt.Printf("\n\tECC signature succeeded!\n\n")
+	}
+
+	// fmt.Printf("Round Info RAW: %v\n\n", round)
+
+	// rsapubkey, _ := rsa.LoadPublicKeyFromPem([]byte(
+	// 	registration.TlsCertificate))
+	// signature.VerifyRsa(ri, rsapubkey)
+	// if err != nil {
+	// 	fmt.Printf("RSA signature failed: %v", err)
+	// 	fmt.Printf("use trace logging for sig details")
+	// } else {
+	// 	fmt.Printf("RSA signature succeeded!")
+	// }
+}
+
+func dumpRounds(roundIDs []id.Round, user *xxdk.E2e) []rounds.Round {
+	numRequests := len(roundIDs)
+	requestCh := make(chan rounds.Round, numRequests)
+
+	rcb := func(round rounds.Round, success bool) {
+		if !success {
+			fmt.Printf("round %v lookup failed", round.ID)
+		}
+		requestCh <- round
+	}
+
+	for i := range roundIDs {
+		rid := roundIDs[i]
+		err := user.GetCmix().LookupHistoricalRound(rid, rcb)
+		if err != nil {
+			fmt.Printf("error on %v: %v", rid, err)
+		}
+	}
+
+	roundInfos := make([]rounds.Round, 0)
+	for done := 0; done < numRequests; done++ {
+		res := <-requestCh
+		roundInfos = append(roundInfos, res)
+		jww.DEBUG.Printf("request complete: %v", res)
+	}
+	return roundInfos
+}
+
 func parseRoundIDs(roundStrs []string) []id.Round {
 	var roundIDs []id.Round
 	for _, r := range roundStrs {
diff --git a/cmd/flags.go b/cmd/flags.go
index 5244b7a12b62ee1e1c7d5a718f45b2bbccfad005..8d9c827f2b38cb2ff1668cc9431922fc32eaa99e 100644
--- a/cmd/flags.go
+++ b/cmd/flags.go
@@ -148,4 +148,9 @@ const (
 	udSearchEmailFlag    = "searchemail"
 	udSearchPhoneFlag    = "searchphone"
 	udBatchAddFlag       = "batchadd"
+
+	///////////////// pickup subcommand flags //////////////////////////////
+	pickupGW    = "gateway"
+	pickupID    = "id"
+	pickupEphID = "ephid"
 )
diff --git a/cmd/pickup.go b/cmd/pickup.go
new file mode 100644
index 0000000000000000000000000000000000000000..ee4afbe53c923e9ec864e6a5b20536fe91b78a01
--- /dev/null
+++ b/cmd/pickup.go
@@ -0,0 +1,215 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright © 2020 xx network SEZC                                          //
+//                                                                           //
+// Use of this source code is governed by a license that can be found in the //
+// LICENSE file                                                              //
+///////////////////////////////////////////////////////////////////////////////
+
+// Package cmd initializes the CLI and config parsers as well as the logger.
+package cmd
+
+import (
+	"encoding/binary"
+	"fmt"
+	"time"
+
+	"github.com/pkg/errors"
+
+	"github.com/spf13/cobra"
+	jww "github.com/spf13/jwalterweatherman"
+	"github.com/spf13/viper"
+	"gitlab.com/elixxir/client/cmix/pickup"
+	pb "gitlab.com/elixxir/comms/mixmessages"
+	"gitlab.com/elixxir/primitives/states"
+	"gitlab.com/xx_network/crypto/csprng"
+	"gitlab.com/xx_network/crypto/randomness"
+	"gitlab.com/xx_network/primitives/id"
+	"gitlab.com/xx_network/primitives/id/ephemeral"
+	"gitlab.com/xx_network/primitives/ndf"
+)
+
+// pickupCmd allows the user to view network information about a specific
+// round on the network.
+var pickupCmd = &cobra.Command{
+	Use:   "pickup",
+	Short: "Download the bloomfilter and messages for a round",
+	Args:  cobra.MinimumNArgs(1),
+	Run: func(cmd *cobra.Command, args []string) {
+		roundIDs := parseRoundIDs(args)
+
+		cmixParams, e2eParams := initParams()
+		authCbs := makeAuthCallbacks(
+			viper.GetBool(unsafeChannelCreationFlag), e2eParams)
+		user := initE2e(cmixParams, e2eParams, authCbs)
+		err := user.StartNetworkFollower(5 * time.Second)
+		if err != nil {
+			jww.FATAL.Panicf("%+v", err)
+		}
+
+		connected := make(chan bool, 10)
+		user.GetCmix().AddHealthCallback(
+			func(isconnected bool) {
+				connected <- isconnected
+			})
+		waitUntilConnected(connected)
+
+		ndf := user.GetStorage().GetNDF()
+
+		gwID := getGatewayID(ndf)
+		clientIDStr := viper.GetString(pickupID)
+		var clientID *id.ID
+		if clientIDStr != "" {
+			clientID = parseRecipient(viper.GetString(pickupID))
+		}
+		eID := viper.GetInt64(pickupEphID)
+		if eID != 0 {
+			fmt.Printf("EphID Override: %d\n", eID)
+		}
+
+		// First we get round info, then we use the timestamps to
+		// calculate the right ephID and retrieve the right bloom filter
+		roundInfos := dumpRounds(roundIDs, user)
+		for i := range roundInfos {
+			ri := roundInfos[i]
+			var ephIDs []ephemeral.Id
+			if clientID != nil {
+				ephIDs = getEphID(clientID,
+					uint(ri.AddressSpaceSize),
+					ri.Timestamps[states.QUEUED])
+			} else {
+				ephIDs = append(ephIDs, int2EphID(eID,
+					uint(ri.AddressSpaceSize)))
+			}
+
+			for j := range ephIDs {
+				ephID := ephIDs[j]
+				fmt.Printf("Getting messages for %s, %d\n",
+					ri.ID, ephID.Int64())
+				msgRsp, err := getMessagesFromRound(gwID, ri.ID,
+					ephID,
+					user.GetComms())
+				if err != nil {
+					fmt.Printf("\n\nround pickup: %+v\n\n",
+						err)
+				}
+				fmt.Printf("=====ROUNDPICKUP=====\n\n%+v\n\n\n", msgRsp)
+				fmt.Printf("%d messages for user %d", len(msgRsp.Messages), ephIDs)
+				for k := range msgRsp.Messages {
+					fmt.Printf("%v\n", msgRsp.Messages[k].PayloadA)
+				}
+			}
+		}
+	},
+}
+
+func init() {
+	pickupCmd.Flags().StringP(pickupGW, "g", "",
+		"gateway (base64 address string) to download from")
+	bindFlagHelper(pickupGW, pickupCmd)
+
+	pickupCmd.Flags().StringP(pickupID, "i", "",
+		"id to check")
+	bindFlagHelper(pickupID, pickupCmd)
+
+	pickupCmd.Flags().Int64P(pickupEphID, "e", 0,
+		"ignore id lookup and use this specific eph id (signed int)")
+	bindFlagHelper(pickupEphID, pickupCmd)
+
+	rootCmd.AddCommand(pickupCmd)
+}
+
+func int2EphID(in int64, addrSize uint) ephemeral.Id {
+	var out [8]byte
+	mask := uint64(0xFFFFFFFFFFFFFFFF) >> (64 - addrSize)
+
+	// NOTE: This is just reversing the Int64() function. I have
+	// no idea why it was done this way...
+	x := in
+	if x < 0 {
+		x = ^x
+		x = x << 1
+		x = x | 1
+	} else {
+		x = x << 1
+	}
+
+	shifted := uint64(x) & mask
+	fmt.Printf("Shifted: %d, %d, %d, %d\n", addrSize, mask, in, shifted)
+
+	binary.BigEndian.PutUint64(out[:], shifted)
+	return ephemeral.Id(out)
+}
+
+func getEphID(id *id.ID, addrSize uint,
+	roundStart time.Time) []ephemeral.Id {
+
+	fmt.Printf("Getting EphIDs for %s", roundStart)
+
+	ephIDs, err := ephemeral.GetIdsByRange(id,
+		addrSize,
+		roundStart,
+		time.Duration(12*time.Hour))
+	if err != nil {
+		jww.FATAL.Panicf("%+v", err)
+	}
+
+	if len(ephIDs) == 0 {
+		jww.FATAL.Panicf("No ephemeral ids found!")
+	}
+
+	eIDs := make([]ephemeral.Id, len(ephIDs))
+	for i := range ephIDs {
+		eIDs[i] = ephIDs[i].Id
+	}
+
+	return eIDs
+}
+func getGatewayID(ndf *ndf.NetworkDefinition) *id.ID {
+	gateways := ndf.Gateways
+	gwID := viper.GetString(pickupGW)
+
+	if gwID == "" {
+		rng := csprng.NewSystemRNG()
+		i := randomness.ReadRangeUint32(0, uint32(len(gateways)), rng)
+		id, err := id.Unmarshal([]byte(gateways[i].ID))
+		if err != nil {
+			jww.FATAL.Panicf("%+v", err)
+		}
+		fmt.Printf("selected random gw: %s\n", id)
+		return id
+	}
+
+	for i := range gateways {
+		curID, _ := id.Unmarshal(gateways[i].ID)
+		jww.DEBUG.Printf("%s ==? %s", gwID, curID)
+		if curID.String() == gwID {
+			return curID
+		}
+	}
+
+	jww.FATAL.Panicf("%s is not a gateway in the NDF", gwID)
+	return nil
+}
+
+func getBloomFilter(targetGW string, ephID int64) *pb.ClientBlooms {
+	return nil
+}
+
+func getMessagesFromRound(targetGW *id.ID, roundID id.Round,
+	ephID ephemeral.Id, comms pickup.MessageRetrievalComms) (
+	*pb.GetMessagesResponse, error) {
+
+	host, ok := comms.GetHost(targetGW)
+	if !ok {
+		return nil, errors.Errorf("can't find host %s", targetGW)
+	}
+	msgReq := &pb.GetMessages{
+		ClientID: ephID[:],
+		RoundID:  uint64(roundID),
+		Target:   targetGW.Marshal(),
+	}
+
+	jww.DEBUG.Printf("Sending request: %+v", msgReq)
+
+	return comms.RequestMessages(host, msgReq)
+}
diff --git a/cmix/gateway/hostPool.go b/cmix/gateway/hostPool.go
index ca9e0c7b606cb50bd27e932f8da625fcc39aaae9..c90a825fafa8b9b4a9fee9988fe5ab94d1b347dc 100644
--- a/cmix/gateway/hostPool.go
+++ b/cmix/gateway/hostPool.go
@@ -13,8 +13,13 @@
 package gateway
 
 import (
-	"encoding/binary"
 	"encoding/json"
+	"math"
+	"sort"
+	"strings"
+	"sync"
+	"time"
+
 	"github.com/pkg/errors"
 	jww "github.com/spf13/jwalterweatherman"
 	"gitlab.com/elixxir/client/storage"
@@ -23,17 +28,12 @@ import (
 	"gitlab.com/elixxir/crypto/fastRNG"
 	"gitlab.com/elixxir/crypto/shuffle"
 	"gitlab.com/xx_network/comms/connect"
+	"gitlab.com/xx_network/crypto/randomness"
 	"gitlab.com/xx_network/primitives/id"
 	"gitlab.com/xx_network/primitives/ndf"
 	"golang.org/x/net/context"
 	"google.golang.org/grpc"
 	"google.golang.org/grpc/balancer"
-	"io"
-	"math"
-	"sort"
-	"strings"
-	"sync"
-	"time"
 )
 
 // List of errors that initiate a Host replacement
@@ -496,7 +496,8 @@ func (h *HostPool) getAny(length uint32, excluded []*id.ID) []*connect.Host {
 		}
 
 		// Check the next HostPool index
-		gwIdx := readRangeUint32(0, h.poolParams.PoolSize, rng)
+		gwIdx := randomness.ReadRangeUint32(0, h.poolParams.PoolSize,
+			rng)
 		if _, ok := checked[gwIdx]; !ok {
 			result = append(result, h.hostList[gwIdx])
 			checked[gwIdx] = nil
@@ -537,7 +538,8 @@ func (h *HostPool) getPreferred(targets []*id.ID) []*connect.Host {
 			continue
 		}
 
-		gwIdx := readRangeUint32(0, h.poolParams.PoolSize, rng)
+		gwIdx := randomness.ReadRangeUint32(0, h.poolParams.PoolSize,
+			rng)
 		if _, ok := checked[gwIdx]; !ok {
 			result[i] = h.hostList[gwIdx]
 			checked[gwIdx] = nil
@@ -591,7 +593,8 @@ func (h *HostPool) selectGateway() *id.ID {
 	// Loop until a replacement Host is found
 	for {
 		// Randomly select a new Gw by index in the NDF
-		ndfIdx := readRangeUint32(0, uint32(len(h.ndf.Gateways)), rng)
+		ndfIdx := randomness.ReadRangeUint32(0,
+			uint32(len(h.ndf.Gateways)), rng)
 
 		// Use the random ndfIdx to obtain a GwId from the NDF
 		gwId, err := id.Unmarshal(h.ndf.Gateways[ndfIdx].ID)
@@ -694,7 +697,7 @@ func (h *HostPool) forceAdd(gwId *id.ID) error {
 	}
 
 	// Randomly select another Gateway in the HostPool for replacement
-	poolIdx := readRangeUint32(0, h.poolParams.PoolSize, rng)
+	poolIdx := randomness.ReadRangeUint32(0, h.poolParams.PoolSize, rng)
 	return h.replaceHost(gwId, poolIdx)
 }
 
@@ -826,31 +829,3 @@ func getPoolSize(ndfLen, maxSize uint32) (uint32, error) {
 	}
 	return poolSize, nil
 }
-
-// readUint32 reads an integer from an io.Reader (which should be a CSPRNG).
-func readUint32(rng io.Reader) uint32 {
-	var rndBytes [4]byte
-	i, err := rng.Read(rndBytes[:])
-	if i != 4 || err != nil {
-		jww.FATAL.Panicf("cannot read from rng: %+v", err)
-	}
-	return binary.BigEndian.Uint32(rndBytes[:])
-}
-
-// readRangeUint32 reduces an integer from 0, MaxUint32 to the range start, end.
-func readRangeUint32(start, end uint32, rng io.Reader) uint32 {
-	size := end - start
-	// Note that we could just do the part inside the () here, but then extra
-	// can == size which means a little range is wasted; either choice seems
-	// negligible, so we went with the "more correct"
-	extra := (math.MaxUint32%size + 1) % size
-	limit := math.MaxUint32 - extra
-	// Loop until we read something inside the limit
-	for {
-		res := readUint32(rng)
-		if res > limit {
-			continue
-		}
-		return (res % size) + start
-	}
-}
diff --git a/go.mod b/go.mod
index c30177adab05391441f4195854120bf150d307ba..9544ccf3603961767bbd94d0993cdb30e6b98b0e 100644
--- a/go.mod
+++ b/go.mod
@@ -17,7 +17,7 @@ require (
 	gitlab.com/elixxir/ekv v0.1.7
 	gitlab.com/elixxir/primitives v0.0.3-0.20220606195757-40f7a589347f
 	gitlab.com/xx_network/comms v0.0.4-0.20220630163702-f3d372ef6acd
-	gitlab.com/xx_network/crypto v0.0.5-0.20220606200528-3f886fe49e81
+	gitlab.com/xx_network/crypto v0.0.5-0.20220729013538-7952978b310b
 	gitlab.com/xx_network/primitives v0.0.4-0.20220712193914-aebd8544396e
 	go.uber.org/ratelimit v0.2.0
 	golang.org/x/crypto v0.0.0-20220128200615-198e4374d7ed
diff --git a/go.sum b/go.sum
index e8adcd01305845b6db74898bb27221cf3bf81cbf..4d8455a4272c1b161221763923b6ac54b1483324 100644
--- a/go.sum
+++ b/go.sum
@@ -301,6 +301,10 @@ gitlab.com/xx_network/crypto v0.0.5-0.20220222212031-750f7e8a01f4/go.mod h1:6apv
 gitlab.com/xx_network/crypto v0.0.5-0.20220317171841-084640957d71/go.mod h1:/SJf+R75E+QepdTLh0H1/udsovxx2Q5ru34q1v0umKk=
 gitlab.com/xx_network/crypto v0.0.5-0.20220606200528-3f886fe49e81 h1:9HK48ZEGFKLm3HBcE/FdQitllJRYPPS0zeaiRL+MBhI=
 gitlab.com/xx_network/crypto v0.0.5-0.20220606200528-3f886fe49e81/go.mod h1:/SJf+R75E+QepdTLh0H1/udsovxx2Q5ru34q1v0umKk=
+gitlab.com/xx_network/crypto v0.0.5-0.20220729011416-22620d3c99d3 h1:Os4H4+nBkGtDOu00Pferd6uprDWG3kMrM8HWCj71QeI=
+gitlab.com/xx_network/crypto v0.0.5-0.20220729011416-22620d3c99d3/go.mod h1:/SJf+R75E+QepdTLh0H1/udsovxx2Q5ru34q1v0umKk=
+gitlab.com/xx_network/crypto v0.0.5-0.20220729013538-7952978b310b h1:agxNQUORADob4R6FhucBQDLPWFQ0D2poMyT4SDnPuyo=
+gitlab.com/xx_network/crypto v0.0.5-0.20220729013538-7952978b310b/go.mod h1:/SJf+R75E+QepdTLh0H1/udsovxx2Q5ru34q1v0umKk=
 gitlab.com/xx_network/primitives v0.0.0-20200803231956-9b192c57ea7c/go.mod h1:wtdCMr7DPePz9qwctNoAUzZtbOSHSedcK++3Df3psjA=
 gitlab.com/xx_network/primitives v0.0.0-20200804183002-f99f7a7284da/go.mod h1:OK9xevzWCaPO7b1wiluVJGk7R5ZsuC7pHY5hteZFQug=
 gitlab.com/xx_network/primitives v0.0.2/go.mod h1:cs0QlFpdMDI6lAo61lDRH2JZz+3aVkHy+QogOB6F/qc=