diff --git a/bindings/preimage.go b/bindings/preimage.go
new file mode 100644
index 0000000000000000000000000000000000000000..ff9e7571869d8c49cf776b0830db30a1698d7892
--- /dev/null
+++ b/bindings/preimage.go
@@ -0,0 +1,66 @@
+package bindings
+
+import (
+	"github.com/pkg/errors"
+	"gitlab.com/elixxir/client/storage/edge"
+	"gitlab.com/xx_network/primitives/id"
+)
+
+
+type PreimageNotification interface{
+	Notify(identity []byte, deleted bool)
+}
+
+func (c *Client)RegisterPreimageCallback(identity []byte, pin PreimageNotification){
+
+	iid := &id.ID{}
+	copy(iid[:], identity)
+
+	cb := func(localIdentity *id.ID, deleted bool){
+		pin.Notify(localIdentity[:],deleted)
+	}
+
+	c.api.GetStorage().GetEdge().AddUpdateCallback(iid, cb)
+}
+
+func (c *Client)GetPreimages(identity []byte)(*PreimageList, error){
+
+	iid := &id.ID{}
+	copy(iid[:], identity)
+
+	list, exist := c.api.GetStorage().GetEdge().Get(iid)
+	if !exist{
+		return nil, errors.Errorf("Could not find a preimage list for %s", iid)
+	}
+
+	return &PreimageList{list: list}, nil
+}
+
+type Preimage struct{
+	pi edge.Preimage
+}
+
+func (pi *Preimage)Get()[]byte{
+	return pi.pi.Data
+}
+
+func (pi *Preimage)Type()string{
+	return pi.pi.Type
+}
+
+func (pi *Preimage)Source()[]byte{
+	return pi.pi.Source
+}
+
+
+type PreimageList struct{
+	list edge.Preimages
+}
+
+func (pil *PreimageList)Len()int{
+	return len(pil.list)
+}
+
+func (pil *PreimageList)Get(index int)*Preimage{
+	return &Preimage{pi:pil.list[index]}
+}
\ No newline at end of file
diff --git a/go.mod b/go.mod
index dbe4d79a58accf98ee34cc3b003b82eb7dcac69e..3e85ae6017d86c931b6f2e67d120c6fbf012affc 100644
--- a/go.mod
+++ b/go.mod
@@ -18,7 +18,7 @@ require (
 	github.com/spf13/viper v1.7.1
 	gitlab.com/elixxir/bloomfilter v0.0.0-20200930191214-10e9ac31b228
 	gitlab.com/elixxir/comms v0.0.4-0.20211014164523-495493efb970
-	gitlab.com/elixxir/crypto v0.0.7-0.20211017232951-ba1a65ee7b6e
+	gitlab.com/elixxir/crypto v0.0.7-0.20211020151749-ff7236fb494a
 	gitlab.com/elixxir/ekv v0.1.5
 	gitlab.com/elixxir/primitives v0.0.3-0.20211014164029-06022665b576
 	gitlab.com/xx_network/comms v0.0.4-0.20211014163953-e774276b83ae
diff --git a/go.sum b/go.sum
index 37d23fd0792d608122530d1b2d168f77b572f356..bc8b979fe868538cf06cd81849f9163543071c43 100644
--- a/go.sum
+++ b/go.sum
@@ -261,6 +261,8 @@ gitlab.com/elixxir/crypto v0.0.7-0.20211014164205-95915de2ac0d h1:tI3YYoHVb/KViR
 gitlab.com/elixxir/crypto v0.0.7-0.20211014164205-95915de2ac0d/go.mod h1:teuTEXyqsqo4N/J1sshcTg9xYOt+wNTurop7pkZOiCg=
 gitlab.com/elixxir/crypto v0.0.7-0.20211017232951-ba1a65ee7b6e h1:JCYcXV9GBvOVRfYhm1e2b52AnvPQrEQLmOR9XbjzE8k=
 gitlab.com/elixxir/crypto v0.0.7-0.20211017232951-ba1a65ee7b6e/go.mod h1:teuTEXyqsqo4N/J1sshcTg9xYOt+wNTurop7pkZOiCg=
+gitlab.com/elixxir/crypto v0.0.7-0.20211020151749-ff7236fb494a h1:8mrk1jGNMAP1xYnvq67mNP6n42Xiu0a5NsYQ3ztXxgM=
+gitlab.com/elixxir/crypto v0.0.7-0.20211020151749-ff7236fb494a/go.mod h1:teuTEXyqsqo4N/J1sshcTg9xYOt+wNTurop7pkZOiCg=
 gitlab.com/elixxir/ekv v0.1.5 h1:R8M1PA5zRU1HVnTyrtwybdABh7gUJSCvt1JZwUSeTzk=
 gitlab.com/elixxir/ekv v0.1.5/go.mod h1:e6WPUt97taFZe5PFLPb1Dupk7tqmDCTQu1kkstqJvw4=
 gitlab.com/elixxir/primitives v0.0.0-20200731184040-494269b53b4d/go.mod h1:OQgUZq7SjnE0b+8+iIAT2eqQF+2IFHn73tOo+aV11mg=
diff --git a/groupChat/makeGroup.go b/groupChat/makeGroup.go
index f3c5544c9e6b46a6a747e6ef96d1f7bc870e7aae..a9aa01838d1c6db25cf71cc79e2631bbb4b01371 100644
--- a/groupChat/makeGroup.go
+++ b/groupChat/makeGroup.go
@@ -11,6 +11,7 @@ import (
 	"github.com/pkg/errors"
 	jww "github.com/spf13/jwalterweatherman"
 	gs "gitlab.com/elixxir/client/groupChat/groupStore"
+	"gitlab.com/elixxir/client/storage/edge"
 	"gitlab.com/elixxir/crypto/contact"
 	"gitlab.com/elixxir/crypto/fastRNG"
 	"gitlab.com/elixxir/crypto/group"
@@ -87,6 +88,15 @@ func (m Manager) MakeGroup(membership []*id.ID, name, msg []byte) (gs.Group,
 	// Send all group requests
 	roundIDs, status, err := m.sendRequests(g)
 
+	if err==nil{
+		edgeStore := m.store.GetEdge()
+		edgeStore.Add(edge.Preimage{
+			Data:   g.ID[:],
+			Type:   "group",
+			Source: g.ID[:],
+		},m.client.GetUser().ReceptionID)
+	}
+
 	return g, roundIDs, status, err
 }
 
diff --git a/groupChat/manager.go b/groupChat/manager.go
index 92081c060859f180e08c34693d80668b159f3f60..3a2416cd6db0dc90e5bb4f74c80a1fccbceb1c8e 100644
--- a/groupChat/manager.go
+++ b/groupChat/manager.go
@@ -16,6 +16,7 @@ import (
 	"gitlab.com/elixxir/client/interfaces/message"
 	"gitlab.com/elixxir/client/stoppable"
 	"gitlab.com/elixxir/client/storage"
+	"gitlab.com/elixxir/client/storage/edge"
 	"gitlab.com/elixxir/client/storage/versioned"
 	"gitlab.com/elixxir/crypto/cyclic"
 	"gitlab.com/elixxir/crypto/fastRNG"
@@ -129,6 +130,13 @@ func (m Manager) JoinGroup(g gs.Group) error {
 		return errors.Errorf(joinGroupErr, g.ID, err)
 	}
 
+	edgeStore := m.store.GetEdge()
+	edgeStore.Add(edge.Preimage{
+		Data:   g.ID[:],
+		Type:   "group",
+		Source: g.ID[:],
+	},m.client.GetUser().ReceptionID)
+
 	jww.DEBUG.Printf("Joined group %s.", g.ID)
 
 	return nil
@@ -140,9 +148,16 @@ func (m Manager) LeaveGroup(groupID *id.ID) error {
 		return errors.Errorf(leaveGroupErr, groupID, err)
 	}
 
+	edgeStore := m.store.GetEdge()
+	err := edgeStore.Remove(edge.Preimage{
+		Data:   groupID[:],
+		Type:   "group",
+		Source: groupID[:],
+	},m.client.GetUser().ReceptionID)
+
 	jww.DEBUG.Printf("Left group %s.", groupID)
 
-	return nil
+	return err
 }
 
 // GetGroups returns a list of all registered groupChat IDs.
diff --git a/groupChat/send.go b/groupChat/send.go
index 0ac72527b60e535b07fd553f4d7a2b386e578d32..29941ce8e71fcc1cea9ec900b01be88d4bea0cc0 100644
--- a/groupChat/send.go
+++ b/groupChat/send.go
@@ -46,7 +46,10 @@ func (m *Manager) Send(groupID *id.ID, message []byte) (id.Round, time.Time,
 		return 0, time.Time{}, errors.Errorf(newCmixMsgErr, err)
 	}
 
-	rid, _, err := m.net.SendManyCMIX(messages, params.GetDefaultCMIX())
+	param := params.GetDefaultCMIX()
+	param.IdentityPreimage = groupID[:]
+
+	rid, _, err := m.net.SendManyCMIX(messages, param)
 	if err != nil {
 		return 0, time.Time{},
 			errors.Errorf(sendManyCmixErr, m.gs.GetUser().ID, groupID, err)
diff --git a/interfaces/params/CMIX.go b/interfaces/params/CMIX.go
index e4142eb5e509dd8ffce8cfd6b3e7a8d33d4fdc46..ee735d1d96026b416c2790c7a7731e5285ca0801 100644
--- a/interfaces/params/CMIX.go
+++ b/interfaces/params/CMIX.go
@@ -17,6 +17,9 @@ type CMIX struct {
 	RoundTries uint
 	Timeout    time.Duration
 	RetryDelay time.Duration
+	// an alternate identity preimage to use on send. If not set, the default
+	// for the sending identity will be used
+	IdentityPreimage []byte
 }
 
 func GetDefaultCMIX() CMIX {
diff --git a/network/follow.go b/network/follow.go
index ca0634be7f36a44e00c487046e488ee57525a55b..bdcdf5deb8d5bda9d72c587f2ceae7d20b80a0f8 100644
--- a/network/follow.go
+++ b/network/follow.go
@@ -321,11 +321,15 @@ func (m *manager) follow(report interfaces.ClientErrorReport, rng csprng.Source,
 	//threshold is the earliest round that will not be excluded from earliest remaining
 	earliestRemaining, roundsWithMessages, roundsUnknown := gwRoundsState.RangeUnchecked(updated,
 		m.param.KnownRoundsThreshold, roundChecker)
+	jww.DEBUG.Printf("Processed RangeUnchecked, Oldest: %d, firstUnchecked: %d, " +
+		"last Checked: %d, threshold: %d, NewEarliestRemaning: %d, NumWithMessages: %d, " +
+		"NumUnknown: %d", updated, gwRoundsState.GetFirstUnchecked(), gwRoundsState.GetLastChecked(),
+		m.param.KnownRoundsThreshold, earliestRemaining, len(roundsWithMessages), len(roundsUnknown))
 
 	_, _, changed := identity.ER.Set(earliestRemaining)
 	if changed {
 		jww.TRACE.Printf("External returns of RangeUnchecked: %d, %v, %v", earliestRemaining, roundsWithMessages, roundsUnknown)
-		jww.DEBUG.Printf("New Earliest Remaining: %d", earliestRemaining)
+		jww.DEBUG.Printf("New Earliest Remaining: %d, Gateways last checked: %d", earliestRemaining, gwRoundsState.GetLastChecked())
 	}
 
 	roundsWithMessages2 := identity.UR.Iterate(func(rid id.Round) bool {
diff --git a/network/message/handler.go b/network/message/handler.go
index ed6891a755a885f186cb7352b60c588b61eb6d13..1931dc84cc5ba3df09ccf22428411e9f2b44a7b2 100644
--- a/network/message/handler.go
+++ b/network/message/handler.go
@@ -12,6 +12,7 @@ import (
 	jww "github.com/spf13/jwalterweatherman"
 	"gitlab.com/elixxir/client/interfaces/message"
 	"gitlab.com/elixxir/client/stoppable"
+	"gitlab.com/elixxir/client/storage/edge"
 	"gitlab.com/elixxir/crypto/e2e"
 	fingerprint2 "gitlab.com/elixxir/crypto/fingerprint"
 	"gitlab.com/elixxir/primitives/format"
@@ -21,6 +22,7 @@ import (
 )
 
 func (m *Manager) handleMessages(stop *stoppable.Single) {
+	preimageList := m.Session.GetEdge()
 	for {
 		select {
 		case <-stop.Quit():
@@ -28,7 +30,7 @@ func (m *Manager) handleMessages(stop *stoppable.Single) {
 			return
 		case bundle := <-m.messageReception:
 			for _, msg := range bundle.Messages {
-				m.handleMessage(msg, bundle)
+				m.handleMessage(msg, bundle, preimageList)
 			}
 			bundle.Finish()
 		}
@@ -36,7 +38,7 @@ func (m *Manager) handleMessages(stop *stoppable.Single) {
 
 }
 
-func (m *Manager) handleMessage(ecrMsg format.Message, bundle Bundle) {
+func (m *Manager) handleMessage(ecrMsg format.Message, bundle Bundle, edge *edge.Store) {
 	// We've done all the networking, now process the message
 	fingerprint := ecrMsg.GetKeyFP()
 	msgDigest := ecrMsg.Digest()
@@ -51,14 +53,27 @@ func (m *Manager) handleMessage(ecrMsg format.Message, bundle Bundle) {
 	var relationshipFingerprint []byte
 
 	//check if the identity fingerprint matches
-	forMe := fingerprint2.CheckIdentityFP(ecrMsg.GetIdentityFP(),
-		ecrMsg.GetContents(), identity.Source)
+	//first check if a list is present in store for the receiving source
+	forMe := false
+	preimagelist, exist := edge.Get(identity.Source)
+	if exist{
+		//if it exists, check against all in the list
+		for i:=0;i<len(preimagelist)&&!forMe;i++{
+			forMe = fingerprint2.CheckIdentityFP(ecrMsg.GetIdentityFP(),
+				ecrMsg.GetContents(), preimagelist[i].Data)
+		}
+	}else{
+		//if it doesnt exist, check against the default fingerprint for the identity
+		forMe = fingerprint2.CheckIdentityFP(ecrMsg.GetIdentityFP(),
+			ecrMsg.GetContents(), identity.Source[:])
+	}
+
 	if !forMe {
 		if jww.GetLogThreshold() == jww.LevelTrace {
 			expectedFP := fingerprint2.IdentityFP(ecrMsg.GetContents(),
-				identity.Source)
+				identity.Source[:])
 			jww.TRACE.Printf("Message for %d (%s) failed identity "+
-				"check: %v (expected) vs %v (received)", identity.EphId,
+				"check: %v (expected-default) vs %v (received)", identity.EphId,
 				identity.Source, expectedFP, ecrMsg.GetIdentityFP())
 		}
 
diff --git a/network/message/sendCmix.go b/network/message/sendCmix.go
index bfb57a56903cb9f4f23e46cae2c59657c0d06da1..5847e4e15631424d0b4165d11d49e0ec980cf98d 100644
--- a/network/message/sendCmix.go
+++ b/network/message/sendCmix.go
@@ -135,7 +135,7 @@ func sendCmixHelper(sender *gateway.Sender, msg format.Message,
 		stream := rng.GetStream()
 
 		wrappedMsg, encMsg, ephID, err := buildSlotMessage(msg, recipient,
-			firstGateway, stream, senderId, bestRound, roundKeys)
+			firstGateway, stream, senderId, bestRound, roundKeys, cmixParams)
 		if err != nil {
 			stream.Close()
 			return 0, ephemeral.Id{}, err
diff --git a/network/message/sendCmixUtils.go b/network/message/sendCmixUtils.go
index 4e71f5731f775386d9ab3afa1d10316214d67b32..7535a66d97f8b66396e92e2c3284e5ff6488a399 100644
--- a/network/message/sendCmixUtils.go
+++ b/network/message/sendCmixUtils.go
@@ -10,6 +10,7 @@ package message
 import (
 	"github.com/pkg/errors"
 	jww "github.com/spf13/jwalterweatherman"
+	"gitlab.com/elixxir/client/interfaces/params"
 	"gitlab.com/elixxir/client/storage"
 	"gitlab.com/elixxir/client/storage/cmix"
 	pb "gitlab.com/elixxir/comms/mixmessages"
@@ -119,7 +120,7 @@ func processRound(instance *network.Instance, session *storage.Session,
 // the recipient.
 func buildSlotMessage(msg format.Message, recipient *id.ID, target *id.ID,
 	stream *fastRNG.Stream, senderId *id.ID, bestRound *pb.RoundInfo,
-	roundKeys *cmix.RoundKeys) (*pb.GatewaySlot, format.Message, ephemeral.Id,
+	roundKeys *cmix.RoundKeys, param params.CMIX) (*pb.GatewaySlot, format.Message, ephemeral.Id,
 	error) {
 
 	// Set the ephemeral ID
@@ -139,8 +140,14 @@ func buildSlotMessage(msg format.Message, recipient *id.ID, target *id.ID,
 
 	msg.SetEphemeralRID(ephIdFilled[:])
 
+	// use the alternate identity preimage if it is set
+	preimage := recipient[:]
+	if param.IdentityPreimage!=nil{
+		preimage = param.IdentityPreimage
+	}
+
 	// Set the identity fingerprint
-	ifp := fingerprint.IdentityFP(msg.GetContents(), recipient)
+	ifp := fingerprint.IdentityFP(msg.GetContents(), preimage)
 
 	msg.SetIdentityFP(ifp)
 
diff --git a/network/message/sendManyCmix.go b/network/message/sendManyCmix.go
index 3c212f745846c2b60747517d3759a0d019e5528d..60267b607bb69a008bf2409e85687549c445f8c4 100644
--- a/network/message/sendManyCmix.go
+++ b/network/message/sendManyCmix.go
@@ -115,7 +115,7 @@ func sendManyCmixHelper(sender *gateway.Sender, msgs map[id.ID]format.Message,
 		i := 0
 		for recipient, msg := range msgs {
 			slots[i], encMsgs[i], ephemeralIds[i], err = buildSlotMessage(
-				msg, &recipient, firstGateway, stream, senderId, bestRound, roundKeys)
+				msg, &recipient, firstGateway, stream, senderId, bestRound, roundKeys, param)
 			if err != nil {
 				return 0, []ephemeral.Id{}, errors.Errorf("failed to build "+
 					"slot message for %s: %+v", recipient, err)
diff --git a/storage/edge/edge.go b/storage/edge/edge.go
new file mode 100644
index 0000000000000000000000000000000000000000..8b2a050eda45df5fd5326ae4bc88b8eccb21dde8
--- /dev/null
+++ b/storage/edge/edge.go
@@ -0,0 +1,215 @@
+package edge
+
+import (
+	"encoding/json"
+	"github.com/pkg/errors"
+	jww "github.com/spf13/jwalterweatherman"
+	"gitlab.com/elixxir/client/storage/versioned"
+	"gitlab.com/xx_network/primitives/id"
+	"gitlab.com/xx_network/primitives/netTime"
+	"sync"
+)
+
+// This stores Preimages which can be used with the identity
+// fingerprint system
+
+const(
+	edgeStorePrefix  = "edgeStore"
+	edgeStoreKey     = "edgeStoreKey"
+	edgeStoreVersion = 0
+)
+
+
+type ListUpdateCallBack func(identity *id.ID, deleted bool)
+
+type Store struct{
+	kv *versioned.KV
+	edge map[id.ID]Preimages
+	callbacks map[id.ID][]ListUpdateCallBack
+	mux *sync.RWMutex
+}
+
+// NewStore creates a new edge store object and inserts the default
+// Preimages for the base identity
+func NewStore(kv *versioned.KV, baseIdentity *id.ID)(*Store, error){
+	kv = kv.Prefix(edgeStorePrefix)
+
+	s := &Store{
+		kv:   kv,
+		edge: make(map[id.ID]Preimages),
+	}
+
+	defaultPreimages := newPreimages(baseIdentity)
+	err := defaultPreimages.save(kv,baseIdentity)
+	if err!=nil{
+		return nil, errors.WithMessage(err,"Failed to create preimage store, " +
+			"failed to create default Preimages")
+	}
+
+	s.edge[*baseIdentity] = defaultPreimages
+
+	return s, s.save()
+}
+
+func LoadStore(kv *versioned.KV)(*Store, error){
+	kv = kv.Prefix(edgeStorePrefix)
+
+	//load the list of identities with preimage lists
+	obj, err := kv.Get(edgeStoreKey, preimageStoreVersion)
+	if err != nil {
+		return nil, errors.WithMessagef(err,"failed to load edge " +
+			"store")
+	}
+
+	identities := make([]id.ID, 0)
+
+	err = json.Unmarshal(obj.Data, &identities)
+	if err != nil {
+		return nil, errors.WithMessagef(err,"failed to unmarshal edge " +
+			"store")
+	}
+
+	s := &Store{
+		kv:   kv,
+		edge: make(map[id.ID]Preimages),
+	}
+
+	//load the preimage lists for all identities
+	for i := range identities{
+		eid := &identities[i]
+		pimgs, err := loadPreimages(kv,eid)
+		if err!=nil{
+			return nil, err
+		}
+		s.edge[*eid] = pimgs
+	}
+
+	return s, nil
+}
+
+func (s *Store)Add(preimage Preimage, identity *id.ID){
+	s.mux.Lock()
+	defer s.mux.Unlock()
+
+	//get the list to update, create if needed
+	pimgs, exists := s.edge[*identity]
+	if !exists{
+		pimgs = newPreimages(identity)
+	}
+
+	//add to the list
+	pimgs = pimgs.add(preimage)
+
+	//store the updated list
+	if err := pimgs.save(s.kv,identity); err!=nil{
+		jww.FATAL.Panicf("Failed to store preimages list after " +
+			"adding preimage %v to identity %s: %+v", preimage.Data, identity, err)
+	}
+
+	//update the map
+	s.edge[*identity] = pimgs
+	if !exists{
+		err := s.save()
+		if err!=nil{
+			jww.FATAL.Panicf("Failed to store edge store after " +
+				"adding preimage %v to identity %s: %+v", preimage.Data, identity, err)
+		}
+	}
+
+	//call any callbacks to notify
+	for i := range s.callbacks[*identity]{
+		cb := s.callbacks[*identity][i]
+		go cb(identity, false)
+	}
+	return
+}
+
+func (s *Store)Remove(preimage Preimage, identity *id.ID)error{
+	s.mux.Lock()
+	defer s.mux.Unlock()
+
+	pimgs, exists := s.edge[*identity]
+	if !exists{
+		return errors.Errorf("Cannot delete preimage %v from " +
+			"identity %s, identity cannot be found", preimage.Data, identity)
+	}
+	pimgsNew := pimgs.remove(preimage.Data)
+	if len(pimgsNew)==0{
+		delete(s.edge, *identity)
+		if err := s.save(); err!=nil{
+			jww.FATAL.Panicf("Failed to store edge store after " +
+				"removing preimage %v to identity %s: %+v", preimage.Data, identity, err)
+		}
+		if err := pimgsNew.delete(s.kv,identity); err!=nil{
+			jww.FATAL.Panicf("Failed to delete preimage list store after " +
+				"removing preimage %v to identity %s: %+v", preimage.Data, identity, err)
+		}
+		//call any callbacks to notify
+		for i := range s.callbacks[*identity]{
+			cb := s.callbacks[*identity][i]
+			go cb(identity, true)
+		}
+		return nil
+	}
+
+	if err := pimgsNew.save(s.kv,identity); err!=nil{
+		jww.FATAL.Panicf("Failed to store preimage list store after " +
+			"removing preimage %v to identity %s: %+v", preimage.Data, identity, err)
+	}
+	s.edge[*identity] = pimgsNew
+
+	//call any callbacks to notify
+	for i := range s.callbacks[*identity]{
+		cb := s.callbacks[*identity][i]
+		go cb(identity, false)
+	}
+	return nil
+}
+
+
+func (s *Store)Get(identity *id.ID)([]Preimage, bool){
+	s.mux.RLock()
+	defer s.mux.RUnlock()
+	primgs, exists := s.edge[*identity]
+	return primgs, exists
+}
+
+func (s *Store)AddUpdateCallback(identity *id.ID, lucb ListUpdateCallBack){
+	s.mux.Lock()
+	defer s.mux.Unlock()
+	list, exists := s.callbacks[*identity]
+	if !exists{
+		list = make([]ListUpdateCallBack, 0, 1)
+	}
+	s.callbacks[*identity] = append(list, lucb)
+}
+
+func (s Store)save()error{
+	identities := make([]id.ID, 0, len(s.edge))
+
+	for eid, _ := range s.edge{
+		identities = append(identities, eid)
+	}
+
+	//marshal
+	data, err := json.Marshal(&identities)
+	if err!=nil{
+		return errors.WithMessagef(err, "Failed to marshal edge list " +
+			"for stroage")
+	}
+
+	// Construct versioning object
+	obj := versioned.Object{
+		Version:   edgeStoreVersion,
+		Timestamp: netTime.Now(),
+		Data:      data,
+	}
+
+	// Save to storage
+	err = s.kv.Set(edgeStoreKey, preimageStoreVersion, &obj)
+	if err != nil {
+		return errors.WithMessagef(err, "Failed to store edge list")
+	}
+
+	return nil
+}
\ No newline at end of file
diff --git a/storage/edge/preimage.go b/storage/edge/preimage.go
new file mode 100644
index 0000000000000000000000000000000000000000..24aa121b37191b67c90d018dbee35075d73648e2
--- /dev/null
+++ b/storage/edge/preimage.go
@@ -0,0 +1,120 @@
+package edge
+
+import (
+	"bytes"
+	"encoding/json"
+	"fmt"
+	"github.com/pkg/errors"
+	"gitlab.com/elixxir/client/storage/versioned"
+	"gitlab.com/xx_network/primitives/id"
+	"gitlab.com/xx_network/primitives/netTime"
+)
+
+
+const (
+	preimageStoreKey     = "preimageStoreKey"
+	preimageStoreVersion = 0
+)
+
+type Preimage struct{
+	Data []byte
+	Type string
+	Source []byte
+}
+
+type Preimages []Preimage
+
+// makes a Preimages object for the given identity and populates
+// it with the default preimage for the identity
+// does not store to disk
+func newPreimages(identity *id.ID) Preimages {
+	var pis Preimages
+	pis = append(pis, Preimage{
+		Data:   identity[:],
+		Type:   "default",
+		Source: identity[:],
+	})
+	return pis
+}
+
+//loads a Preimages object for the given identity
+func loadPreimages(kv *versioned.KV, identity *id.ID)(Preimages, error){
+
+	// Get the data from the kv
+	obj, err := kv.Get(preimageKey(identity), preimageStoreVersion)
+	if err != nil {
+		return nil, errors.WithMessagef(err,"failed to load edge " +
+			"Preimages for identity %s", identity)
+	}
+
+	var preimageList Preimages
+
+	err = json.Unmarshal(obj.Data, &preimageList)
+	if err != nil {
+		return nil, errors.WithMessagef(err,"failed to unmarshal edge " +
+			"Preimages for identity %s", identity)
+	}
+
+	return preimageList, nil
+}
+
+//stores the preimage list to disk
+func (pis Preimages)save(kv *versioned.KV, identity *id.ID)error{
+	//marshal
+	data, err := json.Marshal(&pis)
+	if err!=nil{
+		return errors.WithMessagef(err, "Failed to marshal Preimages list " +
+			"for stroage for identity %s", identity)
+	}
+
+	// Construct versioning object
+	obj := versioned.Object{
+		Version:   preimageStoreVersion,
+		Timestamp: netTime.Now(),
+		Data:      data,
+	}
+
+	// Save to storage
+	err = kv.Set(preimageKey(identity), preimageStoreVersion, &obj)
+	if err != nil {
+		return errors.WithMessagef(err, "Failed to store Preimages list " +
+			"for identity %s", identity)
+	}
+
+	return nil
+}
+
+//adds the preimage to the
+func (pis Preimages)add(pimg Preimage) Preimages {
+	return append(pis,pimg)
+}
+
+func (pis Preimages)remove(data []byte) Preimages {
+
+	for i:=0;i<len(pis);i++{
+		if bytes.Equal(pis[i].Data,data){
+			pis[i] = pis[len(pis)-1]
+			return pis[:len(pis)-1]
+		}
+	}
+
+	return pis
+}
+
+func (pis Preimages)delete(kv *versioned.KV, identity *id.ID)error{
+
+	// Save to storage
+	err := kv.Delete(preimageKey(identity), preimageStoreVersion)
+	if err != nil {
+		return errors.WithMessagef(err, "Failed to delete Preimages list " +
+			"for identity %s", identity)
+	}
+
+	return nil
+}
+
+func preimageKey(identity *id.ID)string{
+	return fmt.Sprintf("%s:%s",preimageStoreKey,identity)
+}
+
+
diff --git a/storage/session.go b/storage/session.go
index fd98a85c22e1d1c3aea073ad3d1d9d6a709c6e1c..e43ddac37f0cf7558d67061f707ba5fcce5e5257 100644
--- a/storage/session.go
+++ b/storage/session.go
@@ -10,6 +10,7 @@
 package storage
 
 import (
+	"gitlab.com/elixxir/client/storage/edge"
 	"gitlab.com/elixxir/client/storage/hostList"
 	"gitlab.com/elixxir/client/storage/rounds"
 	"sync"
@@ -68,6 +69,7 @@ type Session struct {
 	clientVersion       *clientVersion.Store
 	uncheckedRounds     *rounds.UncheckedRoundStore
 	hostList            *hostList.Store
+	edgeCheck			*edge.Store
 }
 
 // Initialize a new Session object
@@ -154,6 +156,10 @@ func New(baseDir, password string, u userInterface.User, currentVersion version.
 
 	s.hostList = hostList.NewStore(s.kv)
 
+	s.edgeCheck, err = edge.NewStore(s.kv,u.ReceptionID)
+	if err != nil {
+		return nil, errors.WithMessage(err, "Failed to edge check store")
+	}
 	return s, nil
 }
 
@@ -232,6 +238,11 @@ func Load(baseDir, password string, currentVersion version.Version,
 
 	s.hostList = hostList.NewStore(s.kv)
 
+	s.edgeCheck, err = edge.LoadStore(s.kv)
+	if err!=nil{
+		return nil, errors.WithMessage(err, "Failed to load edge check store")
+	}
+
 	return s, nil
 }
 
@@ -314,6 +325,13 @@ func (s *Session) HostList() *hostList.Store {
 	return s.hostList
 }
 
+// GetEdge returns the edge preimage store.
+func (s *Session) GetEdge() *edge.Store {
+	s.mux.RLock()
+	defer s.mux.RUnlock()
+	return s.edgeCheck
+}
+
 // Get an object from the session
 func (s *Session) Get(key string) (*versioned.Object, error) {
 	return s.kv.Get(key, currentSessionVersion)