diff --git a/api/client.go b/api/client.go index 56bd570c7a55a23e5a0610851b1d51d59e4ba882..61e95d7067120829aca5b7d1671272f3890eec64 100644 --- a/api/client.go +++ b/api/client.go @@ -27,6 +27,7 @@ import ( "gitlab.com/elixxir/crypto/backup" "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/fastRNG" + "gitlab.com/elixxir/primitives/fact" "gitlab.com/elixxir/primitives/version" "gitlab.com/xx_network/comms/connect" "gitlab.com/xx_network/crypto/csprng" @@ -97,7 +98,7 @@ func NewClient(ndfJSON, storageDir string, password []byte, jww.DEBUG.Printf("User generation took: %s", time.Now().Sub(start)) _, err = checkVersionAndSetupStorage(def, storageDir, password, protoUser, - cmixGrp, e2eGrp, rngStreamGen, false, registrationCode) + cmixGrp, e2eGrp, rngStreamGen, false, registrationCode, nil) if err != nil { return err } @@ -128,7 +129,7 @@ func NewPrecannedClient(precannedID uint, defJSON, storageDir string, protoUser := createPrecannedUser(precannedID, rngStream, cmixGrp, e2eGrp) _, err = checkVersionAndSetupStorage(def, storageDir, password, protoUser, - cmixGrp, e2eGrp, rngStreamGen, true, "") + cmixGrp, e2eGrp, rngStreamGen, true, "", nil) if err != nil { return err } @@ -158,7 +159,7 @@ func NewVanityClient(ndfJSON, storageDir string, password []byte, protoUser := createNewVanityUser(rngStream, cmixGrp, e2eGrp, userIdPrefix) _, err = checkVersionAndSetupStorage(def, storageDir, password, protoUser, - cmixGrp, e2eGrp, rngStreamGen, false, registrationCode) + cmixGrp, e2eGrp, rngStreamGen, false, registrationCode, nil) if err != nil { return err } @@ -199,7 +200,7 @@ func NewClientFromBackup(ndfJSON, storageDir string, sessionPassword, // Note we do not need registration storageSess, err := checkVersionAndSetupStorage(def, storageDir, []byte(sessionPassword), usr, cmixGrp, e2eGrp, rngStreamGen, - false, backUp.RegistrationCode) + false, backUp.RegistrationCode, backUp.UserDiscoveryRegistration.FactList) // Set registration values in storage storageSess.User().SetReceptionRegistrationValidationSignature(backUp. @@ -215,13 +216,6 @@ func NewClientFromBackup(ndfJSON, storageDir string, sessionPassword, return nil, "", err } - err = storageSess.GetUd().RestoreFromBackUp(backUp. - UserDiscoveryRegistration.FactList) - if err != nil { - return nil, "", errors.WithMessage(err, "Could not restore user "+ - "discover storage") - } - return backUp.Contacts.Identities, backUp.JSONParams, nil } @@ -292,7 +286,7 @@ func NewProtoClient_Unsafe(ndfJSON, storageDir string, password, // Set up storage storageSess, err := checkVersionAndSetupStorage(def, storageDir, password, usr, - cmixGrp, e2eGrp, rngStreamGen, false, protoUser.RegCode) + cmixGrp, e2eGrp, rngStreamGen, false, protoUser.RegCode, nil) if err != nil { return err } @@ -955,7 +949,7 @@ func checkVersionAndSetupStorage(def *ndf.NetworkDefinition, storageDir string, password []byte, protoUser user.User, cmixGrp, e2eGrp *cyclic.Group, rngStreamGen *fastRNG.StreamGenerator, - isPrecanned bool, registrationCode string) (*storage.Session, error) { + isPrecanned bool, registrationCode string, backupFacts fact.FactList) (*storage.Session, error) { // Get current client version currentVersion, err := version.ParseVersion(SEMVER) if err != nil { @@ -965,7 +959,8 @@ func checkVersionAndSetupStorage(def *ndf.NetworkDefinition, // Create Storage passwordStr := string(password) storageSess, err := storage.New(storageDir, passwordStr, protoUser, - currentVersion, cmixGrp, e2eGrp, rngStreamGen, def.RateLimits) + currentVersion, cmixGrp, e2eGrp, rngStreamGen, def.RateLimits, + backupFacts) if err != nil { return nil, err } diff --git a/storage/session.go b/storage/session.go index 2ad3042ed7c76758227a42f751f146ae15cc58b4..f03194876fc94ebb1def42cfe8f6f2e79de9993d 100644 --- a/storage/session.go +++ b/storage/session.go @@ -14,6 +14,7 @@ import ( "gitlab.com/elixxir/client/storage/hostList" "gitlab.com/elixxir/client/storage/rounds" "gitlab.com/elixxir/client/storage/ud" + "gitlab.com/elixxir/primitives/fact" "gitlab.com/xx_network/primitives/rateLimiting" "sync" "testing" @@ -98,7 +99,7 @@ func initStore(baseDir, password string) (*Session, error) { func New(baseDir, password string, u userInterface.User, currentVersion version.Version, cmixGrp, e2eGrp *cyclic.Group, rng *fastRNG.StreamGenerator, - rateLimitParams ndf.RateLimiting) (*Session, error) { + rateLimitParams ndf.RateLimiting, backupFacts fact.FactList) (*Session, error) { s, err := initStore(baseDir, password) if err != nil { @@ -180,7 +181,7 @@ func New(baseDir, password string, u userInterface.User, s.bucketStore = utility.NewStoredBucket(uint32(rateLimitParams.Capacity), uint32(rateLimitParams.LeakedTokens), time.Duration(rateLimitParams.LeakDuration), s.kv) - s.ud, err = ud.NewStore(s.kv) + s.ud, err = ud.NewStore(s.kv, backupFacts) if err != nil { return nil, errors.WithMessage(err, "Failed to create ud store") } @@ -527,7 +528,7 @@ func InitTestingSession(i interface{}) *Session { // jww.FATAL.Panicf("Failed to create ring buffer store: %+v", err) //} - s.ud, err = ud.NewStore(s.kv) + s.ud, err = ud.NewStore(s.kv, nil) if err != nil { jww.FATAL.Panicf("Failed to create ud store: %v", err) } diff --git a/storage/ud/facts.go b/storage/ud/facts.go index 33a1ceb8c339894a9ff330bbdaa752cb1f83737b..18bb345316b4e469c59a40a074c34ffd93654857 100644 --- a/storage/ud/facts.go +++ b/storage/ud/facts.go @@ -21,7 +21,6 @@ const ( "%s (%s) is non-empty but not an email. Cancelling backup operation" backupMissingAllZeroesFactErr = "Cannot backup missing facts: Both email and phone facts are empty!" factNotInStoreErr = "Fact %v does not exist in store" - storeStatefulErr = "cannot overwrite ud store which already contains state" ) // Store is the storage object for the higher level ud.Manager object. @@ -36,8 +35,10 @@ type Store struct { mux sync.RWMutex } -// NewStore creates a new, empty Store object. -func NewStore(kv *versioned.KV) (*Store, error) { +// NewStore creates a new Store object. If we are initializing from a backup, +// the backupFacts fact.FactList will be non-nil and initialize the state +// with the backed up data. +func NewStore(kv *versioned.KV, backupFacts fact.FactList) (*Store, error) { kv = kv.Prefix(prefix) s := &Store{ confirmedFacts: make(map[fact.Fact]struct{}, 0), @@ -45,25 +46,11 @@ func NewStore(kv *versioned.KV) (*Store, error) { kv: kv, } - return s, s.save() -} - -// RestoreFromBackUp initializes the confirmedFacts map -// with the backed up fact data. This will error if -// the store is already stateful. -func (s *Store) RestoreFromBackUp(backupData fact.FactList) error { - s.mux.Lock() - defer s.mux.Unlock() - - if len(s.confirmedFacts) != 0 || len(s.unconfirmedFacts) != 0 { - return errors.New(storeStatefulErr) - } - - for _, f := range backupData { + for _, f := range backupFacts { s.confirmedFacts[f] = struct{}{} } - return nil + return s, s.save() } // StoreUnconfirmedFact stores a fact that has been added to UD but has not been diff --git a/storage/ud/facts_test.go b/storage/ud/facts_test.go index 52e51979dbb417f2dd584b50c77c68ecd5167a26..02ff7db9e2946cd3144e1537809abf125e54142c 100644 --- a/storage/ud/facts_test.go +++ b/storage/ud/facts_test.go @@ -21,78 +21,18 @@ func TestNewStore(t *testing.T) { kv := versioned.NewKV(make(ekv.Memstore)) - _, err := NewStore(kv) + _, err := NewStore(kv, nil) if err != nil { t.Errorf("NewStore() produced an error: %v", err) } } -// Unit test -func TestStore_RestoreFromBackUp(t *testing.T) { - - kv := versioned.NewKV(make(ekv.Memstore)) - - s, err := NewStore(kv) - if err != nil { - t.Errorf("NewStore() produced an error: %v", err) - } - - expected := fact.Fact{ - Fact: "josh", - T: fact.Username, - } - - fl := fact.FactList{expected} - - err = s.RestoreFromBackUp(fl) - if err != nil { - t.Fatalf("RestoreFromBackup err: %v", err) - } - - _, exists := s.confirmedFacts[expected] - if !exists { - t.Fatalf("Fact %s does not exist in map", expected) - } - -} - -// Error case. -func TestStore_RestoreFromBackUp_StatefulStore(t *testing.T) { - - kv := versioned.NewKV(make(ekv.Memstore)) - - s, err := NewStore(kv) - if err != nil { - t.Errorf("NewStore() produced an error: %v", err) - } - - confirmId := "confirm" - expected := fact.Fact{ - Fact: "josh", - T: fact.Username, - } - - err = s.StoreUnconfirmedFact(confirmId, expected) - if err != nil { - t.Fatalf("StoreUnconfirmedFact error: %v", err) - } - - // Expected error: should error when restoring on - // a stateful store. - fl := fact.FactList{expected} - err = s.RestoreFromBackUp(fl) - if err == nil { - t.Fatalf("RestoreFromBackup err: %v", err) - } - -} - // Unit test. func TestStore_ConfirmFact(t *testing.T) { kv := versioned.NewKV(make(ekv.Memstore)) - expectedStore, err := NewStore(kv) + expectedStore, err := NewStore(kv, nil) if err != nil { t.Errorf("NewStore() produced an error: %v", err) } @@ -130,7 +70,7 @@ func TestStore_ConfirmFact(t *testing.T) { func TestStore_StoreUnconfirmedFact(t *testing.T) { kv := versioned.NewKV(make(ekv.Memstore)) - expectedStore, err := NewStore(kv) + expectedStore, err := NewStore(kv, nil) if err != nil { t.Errorf("NewStore() produced an error: %v", err) } @@ -192,7 +132,7 @@ func TestStore_DeleteFact(t *testing.T) { func TestStore_BackUpMissingFacts(t *testing.T) { kv := versioned.NewKV(make(ekv.Memstore)) - expectedStore, err := NewStore(kv) + expectedStore, err := NewStore(kv, nil) if err != nil { t.Errorf("NewStore() produced an error: %v", err) } @@ -228,7 +168,7 @@ func TestStore_BackUpMissingFacts(t *testing.T) { func TestStore_BackUpMissingFacts_DuplicateFactType(t *testing.T) { kv := versioned.NewKV(make(ekv.Memstore)) - expectedStore, err := NewStore(kv) + expectedStore, err := NewStore(kv, nil) if err != nil { t.Errorf("NewStore() produced an error: %v", err) } @@ -266,7 +206,7 @@ func TestStore_BackUpMissingFacts_DuplicateFactType(t *testing.T) { func TestStore_GetFacts(t *testing.T) { kv := versioned.NewKV(make(ekv.Memstore)) - testStore, err := NewStore(kv) + testStore, err := NewStore(kv, nil) if err != nil { t.Errorf("NewStore() produced an error: %v", err) } @@ -316,7 +256,7 @@ func TestStore_GetFacts(t *testing.T) { func TestStore_GetFactStrings(t *testing.T) { kv := versioned.NewKV(make(ekv.Memstore)) - testStore, err := NewStore(kv) + testStore, err := NewStore(kv, nil) if err != nil { t.Errorf("NewStore() produced an error: %v", err) }