diff --git a/network/identity/receptionID/fake.go b/network/identity/receptionID/fake.go index 17d45db7a61b6d84559e15d6ec0e27f8f0e09da6..5462690d531fdeeee1b0c2a9e7d60981af8f95aa 100644 --- a/network/identity/receptionID/fake.go +++ b/network/identity/receptionID/fake.go @@ -9,14 +9,15 @@ import ( ) // generateFakeIdentity generates a fake identity of the given size with the -// given random number generator +// given random number generator. func generateFakeIdentity(rng io.Reader, addressSize uint8, now time.Time) (IdentityUse, error) { + // Randomly generate an identity randIdBytes := make([]byte, id.ArrIDLen-1) if _, err := rng.Read(randIdBytes); err != nil { - return IdentityUse{}, errors.WithMessage(err, "failed to "+ - "generate a random identity when none is available") + return IdentityUse{}, errors.WithMessage(err, + "failed to generate a random identity when none is available") } randID := &id.ID{} @@ -33,8 +34,10 @@ func generateFakeIdentity(rng io.Reader, addressSize uint8, return IdentityUse{ Identity: Identity{ - EphId: ephID, - Source: randID, + EphemeralIdentity: EphemeralIdentity{ + EphId: ephID, + Source: randID, + }, AddressSize: addressSize, End: end, ExtraChecks: 0, diff --git a/network/identity/receptionID/fake_test.go b/network/identity/receptionID/fake_test.go index 14bfc096562f428ba8fef8e7816518f3479e2a68..27134207200732d3cdecb943f29a1ecb259a3b42 100644 --- a/network/identity/receptionID/fake_test.go +++ b/network/identity/receptionID/fake_test.go @@ -10,7 +10,7 @@ import ( "time" ) -// Tests Generate Fake identity is consistent and returns a correct result. +// Tests that generateFakeIdentity is consistent and returns a correct result. func Test_generateFakeIdentity(t *testing.T) { rng := rand.New(rand.NewSource(42)) @@ -18,14 +18,14 @@ func Test_generateFakeIdentity(t *testing.T) { end, _ := json.Marshal(time.Unix(0, 1258494203759765625)) startValid, _ := json.Marshal(time.Unix(0, 1258407803759765625)) endValid, _ := json.Marshal(time.Unix(0, 1258494203759765625)) - expected := "{\"EphId\":[0,0,0,0,0,0,46,197]," + - "\"Source\":\"U4x/lrFkvxuXu59LtHLon1sUhPJSCcnZND6SugndnVID\"," + - "\"AddressSize\":" + strconv.Itoa(int(addressSize)) + "," + - "\"End\":" + string(end) + ",\"ExtraChecks\":0," + - "\"StartValid\":" + string(startValid) + "," + - "\"EndValid\":" + string(endValid) + "," + - "\"Ephemeral\":true," + - "\"Fake\":true,\"UR\":null,\"ER\":null,\"CR\":null}" + expected := `{"EphId":[0,0,0,0,0,0,46,197],` + + `"Source":"U4x/lrFkvxuXu59LtHLon1sUhPJSCcnZND6SugndnVID",` + + `"AddressSize":` + strconv.Itoa(int(addressSize)) + `,` + + `"End":` + string(end) + `,"ExtraChecks":0,` + + `"StartValid":` + string(startValid) + `,` + + `"EndValid":` + string(endValid) + `,` + + `"Ephemeral":true,` + + `"Fake":true,"UR":null,"ER":null,"CR":null}` timestamp := time.Date(2009, 11, 17, 20, 34, 58, 651387237, time.UTC) @@ -42,26 +42,31 @@ func Test_generateFakeIdentity(t *testing.T) { } } -// Error path: fails to generate random bytes. +// Error path: generateFakeIdentity fails to generate random bytes. func Test_generateFakeIdentity_RngError(t *testing.T) { rng := strings.NewReader("") timestamp := time.Date(2009, 11, 17, 20, 34, 58, 651387237, time.UTC) + expectedErr := "failed to generate a random identity when none is available" _, err := generateFakeIdentity(rng, 15, timestamp) - if err == nil || !strings.Contains(err.Error(), "failed to generate a random identity") { - t.Errorf("generateFakeIdentity() did not return the correct error on "+ - "failure to generate random bytes: %+v", err) + if err == nil || !strings.Contains(err.Error(), expectedErr) { + t.Errorf("generateFakeIdentity did not return the correct error on "+ + "failure to generate random bytes.\nexpected: %s\nreceived: %+v", + expectedErr, err) } } -// Error path: fails to get the address ID. +// Error path: generateFakeIdentity fails to get the address ID. func Test_generateFakeIdentity_GetEphemeralIdError(t *testing.T) { rng := rand.New(rand.NewSource(42)) timestamp := time.Date(2009, 11, 17, 20, 34, 58, 651387237, time.UTC) + expectedErr := "failed to generate an address ID for random identity " + + "when none is available" _, err := generateFakeIdentity(rng, math.MaxInt8, timestamp) - if err == nil || !strings.Contains(err.Error(), "address ID") { - t.Errorf("generateFakeIdentity() did not return the correct error on "+ - "failure to generate address ID: %+v", err) + if err == nil || !strings.Contains(err.Error(), expectedErr) { + t.Errorf("generateFakeIdentity did not return the correct error on "+ + "failure to generate address ID.\nexpected: %s\nreceived: %+v", + expectedErr, err) } } diff --git a/network/identity/receptionID/identity.go b/network/identity/receptionID/identity.go index 636036ba074f517d01a70fe5ebd3cd2be0e69d08..7d3e46ffe601a299e911caaac949ee82d813d9f1 100644 --- a/network/identity/receptionID/identity.go +++ b/network/identity/receptionID/identity.go @@ -86,16 +86,16 @@ func (i Identity) String() string { } func (i Identity) GoString() string { - str := make([]string, 0, 9) - - str = append(str, "EphId:"+strconv.FormatInt(i.EphId.Int64(), 16)) - str = append(str, "Source:"+i.Source.String()) - str = append(str, "AddressSize:"+strconv.FormatUint(uint64(i.AddressSize), 10)) - str = append(str, "End:"+i.End.String()) - str = append(str, "ExtraChecks:"+strconv.FormatUint(uint64(i.ExtraChecks), 10)) - str = append(str, "StartValid:"+i.StartValid.String()) - str = append(str, "EndValid:"+i.EndValid.String()) - str = append(str, "Ephemeral:"+strconv.FormatBool(i.Ephemeral)) + str := []string{ + "EphId:" + strconv.FormatInt(i.EphId.Int64(), 16), + "Source:" + i.Source.String(), + "AddressSize:" + strconv.FormatUint(uint64(i.AddressSize), 10), + "End:" + i.End.String(), + "ExtraChecks:" + strconv.FormatUint(uint64(i.ExtraChecks), 10), + "StartValid:" + i.StartValid.String(), + "EndValid:" + i.EndValid.String(), + "Ephemeral:" + strconv.FormatBool(i.Ephemeral), + } return "{" + strings.Join(str, ", ") + "}" } diff --git a/network/identity/receptionID/identity_test.go b/network/identity/receptionID/identity_test.go index 2fcb29fb3733fbf70d0e79916dc95488b9a2a585..9a75e9b22f74d42cec859f12c60ac08d547cc2f8 100644 --- a/network/identity/receptionID/identity_test.go +++ b/network/identity/receptionID/identity_test.go @@ -14,8 +14,10 @@ import ( func TestIdentity_EncodeDecode(t *testing.T) { kv := versioned.NewKV(make(ekv.Memstore)) r := Identity{ - EphId: ephemeral.Id{}, - Source: &id.Permissioning, + EphemeralIdentity: EphemeralIdentity{ + EphId: ephemeral.Id{}, + Source: &id.Permissioning, + }, AddressSize: 15, End: netTime.Now().Round(0), ExtraChecks: 12, @@ -35,7 +37,7 @@ func TestIdentity_EncodeDecode(t *testing.T) { } if !r.Equal(rLoad) { - t.Errorf("Registrations are not the same\nsaved: %+v\nloaded: %+v", + t.Errorf("Registrations are not the same.\nsaved: %+v\nloaded: %+v", r, rLoad) } } @@ -43,8 +45,10 @@ func TestIdentity_EncodeDecode(t *testing.T) { func TestIdentity_Delete(t *testing.T) { kv := versioned.NewKV(make(ekv.Memstore)) r := Identity{ - EphId: ephemeral.Id{}, - Source: &id.Permissioning, + EphemeralIdentity: EphemeralIdentity{ + EphId: ephemeral.Id{}, + Source: &id.Permissioning, + }, AddressSize: 15, End: netTime.Now().Round(0), ExtraChecks: 12, diff --git a/network/identity/receptionID/registration.go b/network/identity/receptionID/registration.go index 88dfab231c8360a3ef6f91fd6bf27dd62c537bd9..71be6903f72bea647653851780fd8a59ff958fe5 100644 --- a/network/identity/receptionID/registration.go +++ b/network/identity/receptionID/registration.go @@ -12,8 +12,6 @@ import ( "time" ) -const knownRoundsStorageKey = "krStorage" - type registration struct { Identity UR *store.UnknownRounds @@ -28,9 +26,8 @@ func newRegistration(reg Identity, kv *versioned.KV) (*registration, error) { reg.EndValid = reg.EndValid.Round(0) reg.End = reg.End.Round(0) - // now := netTime.Now() - // Do edge checks to determine if the identity is valid + // now := netTime.Now() // if now.After(reg.End) && reg.ExtraChecks < 1 { // return nil, errors.New("Cannot create a registration for an " + // "identity which has expired") @@ -50,14 +47,13 @@ func newRegistration(reg Identity, kv *versioned.KV) (*registration, error) { r.ER = store.NewEarliestRound(!reg.Ephemeral, kv) cr, err := store.NewCheckedRounds(1500, kv) if err != nil { - jww.FATAL.Printf("Failed to create new CheckedRounds for registration: %+v", err) + jww.FATAL.Printf( + "Failed to create new CheckedRounds for registration: %+v", err) } r.CR = cr // If this is not address, then store everything if !reg.Ephemeral { - // Store known rounds - var err error // Store the registration if err = reg.store(kv); err != nil { return nil, errors.WithMessage(err, "failed to store registration") @@ -105,8 +101,8 @@ func (r *registration) Delete() error { if !r.Ephemeral { r.UR.Delete() if err := r.delete(r.kv); err != nil { - return errors.WithMessagef(err, "Failed to delete registration "+ - "public data %s", r) + return errors.WithMessagef( + err, "Failed to delete registration public data %s", r) } } diff --git a/network/identity/receptionID/store.go b/network/identity/receptionID/store.go index 18a66096d0e1b89b603af6b54239cfdfa897f37b..e13eddfac252e4fd9daf2032f920f0e110a75dfe 100644 --- a/network/identity/receptionID/store.go +++ b/network/identity/receptionID/store.go @@ -15,9 +15,11 @@ import ( "time" ) -const receptionPrefix = "reception" -const receptionStoreStorageKey = "receptionStoreKey" -const receptionStoreStorageVersion = 0 +const ( + receptionPrefix = "reception" + receptionStoreStorageKey = "receptionStoreKey" + receptionStoreStorageVersion = 0 +) type Store struct { // Identities which are being actively checked @@ -46,12 +48,14 @@ func makeIdHash(ephID ephemeral.Id, source *id.ID) idHash { return idH } -// NewStore creates a new reception store that starts empty. +// NewOrLoadStore creates a new reception store that starts empty. func NewOrLoadStore(kv *versioned.KV) *Store { s, err := loadStore(kv) if err != nil { - jww.WARN.Printf("ReceptionID store not found, creating a new one: %+v", err) + jww.WARN.Printf( + "ReceptionID store not found, creating a new one: %+v", err) + s = &Store{ active: []*registration{}, present: make(map[idHash]struct{}), @@ -73,13 +77,15 @@ func loadStore(kv *versioned.KV) (*Store, error) { // Load the versioned object for the reception list vo, err := kv.Get(receptionStoreStorageKey, receptionStoreStorageVersion) if err != nil { - return nil, errors.WithMessage(err, "Failed to get the reception storage list") + return nil, errors.WithMessage(err, + "Failed to get the reception storage list") } // JSON unmarshal identities list var identities []storedReference if err = json.Unmarshal(vo.Data, &identities); err != nil { - return nil, errors.WithMessage(err, "Failed to unmarshal the stored identity list") + return nil, errors.WithMessage(err, + "Failed to unmarshal the stored identity list") } s := &Store{ @@ -89,9 +95,11 @@ func loadStore(kv *versioned.KV) (*Store, error) { } for i, sr := range identities { - s.active[i], err = loadRegistration(sr.Eph, sr.Source, sr.StartValid, s.kv) + s.active[i], err = loadRegistration( + sr.Eph, sr.Source, sr.StartValid, s.kv) if err != nil { - return nil, errors.WithMessagef(err, "failed to load registration for: %+v", + return nil, errors.WithMessagef(err, + "failed to load registration for: %+v", regPrefix(sr.Eph, sr.Source, sr.StartValid)) } s.present[makeIdHash(sr.Eph, sr.Source)] = struct{}{} @@ -154,14 +162,14 @@ func (s *Store) GetIdentity(rng io.Reader, addressSize uint8) (IdentityUse, erro var identity IdentityUse var err error - // If the list is empty, then we return a randomly generated identity to - // poll with so we can continue tracking the network and to further + // If the list is empty, then return a randomly generated identity to poll + // with so that we can continue tracking the network and to further // obfuscate network identities. if len(s.active) == 0 { identity, err = generateFakeIdentity(rng, addressSize, now) if err != nil { - jww.FATAL.Panicf("Failed to generate a new ID when none "+ - "available: %+v", err) + jww.FATAL.Panicf( + "Failed to generate a new ID when none available: %+v", err) } } else { identity, err = s.selectIdentity(rng, now) @@ -193,14 +201,14 @@ func (s *Store) AddIdentity(identity Identity) error { reg, err := newRegistration(identity, s.kv) if err != nil { - return errors.WithMessage(err, "failed to add new identity to "+ - "reception store") + return errors.WithMessage(err, + "Failed to add new identity to reception store") } s.active = append(s.active, reg) s.present[idH] = struct{}{} if !identity.Ephemeral { - if err := s.save(); err != nil { + if err = s.save(); err != nil { jww.FATAL.Panicf("Failed to save reception store after identity "+ "addition: %+v", err) } @@ -297,8 +305,8 @@ func (s *Store) prune(now time.Time) { // Save the list if it changed if lengthBefore != len(s.active) { - - jww.INFO.Printf("Pruned %d identities [%+v]", lengthBefore-len(s.active), pruned) + jww.INFO.Printf( + "Pruned %d identities [%+v]", lengthBefore-len(s.active), pruned) if err := s.save(); err != nil { jww.FATAL.Panicf("Failed to store reception storage: %+v", err) } diff --git a/network/identity/receptionID/store/checkedRounds.go b/network/identity/receptionID/store/checkedRounds.go index e02275a1449e126890bb96ffa32acc5f51475d5a..3ef3a61c07c131c5671fc0729e22df9f85715b49 100644 --- a/network/identity/receptionID/store/checkedRounds.go +++ b/network/identity/receptionID/store/checkedRounds.go @@ -40,7 +40,8 @@ func NewCheckedRounds(maxRounds int, kv *versioned.KV) (*CheckedRounds, error) { // Create a new BlockStore for storing the round IDs to storage store, err := utility.NewBlockStore(itemsPerBlock, numBlocks, kv) if err != nil { - return nil, errors.Errorf("failed to save new checked rounds to storage: %+v", err) + return nil, errors.Errorf( + "failed to save new checked rounds to storage: %+v", err) } // Create new CheckedRounds @@ -63,7 +64,8 @@ func LoadCheckedRounds(maxRounds int, kv *versioned.KV) (*CheckedRounds, error) // get rounds from storage store, rounds, err := utility.LoadBlockStore(kv) if err != nil { - return nil, errors.Errorf("failed to load CheckedRounds from storage: %+v", err) + return nil, errors.Errorf( + "failed to load CheckedRounds from storage: %+v", err) } // Create new CheckedRounds diff --git a/network/identity/receptionID/store/earliestRound.go b/network/identity/receptionID/store/earliestRound.go index 230bb84c3d3470332efd372051311a53842b371f..fe1b60abd17932382d92f1df6d03ca480727d817 100644 --- a/network/identity/receptionID/store/earliestRound.go +++ b/network/identity/receptionID/store/earliestRound.go @@ -9,8 +9,10 @@ import ( "sync" ) -const earliestRoundStorageKey = "unknownRoundStorage" -const earliestRoundStorageVersion = 0 +const ( + earliestRoundStorageKey = "unknownRoundStorage" + earliestRoundStorageVersion = 0 +) type EarliestRound struct { stored bool @@ -25,6 +27,7 @@ func NewEarliestRound(stored bool, kv *versioned.KV) *EarliestRound { kv: kv, rid: 0, } + ur.save() return ur } @@ -38,7 +41,7 @@ func LoadEarliestRound(kv *versioned.KV) *EarliestRound { obj, err := kv.Get(earliestRoundStorageKey, earliestRoundStorageVersion) if err != nil { - jww.FATAL.Panicf("Failed to get the earlest round: %+v", err) + jww.FATAL.Panicf("Failed to get the earliest round: %+v", err) } err = json.Unmarshal(obj.Data, &ur.rid) @@ -71,8 +74,8 @@ func (ur *EarliestRound) save() { } } -// Set returns the updated earliest round, the old earliest round, and if they are changed. -// Updates the earliest round if it is newer than stored one +// Set returns the updated earliest round, the old earliest round, and if they +// are changed. Updates the earliest round if it is newer than stored one. func (ur *EarliestRound) Set(rid id.Round) (id.Round, id.Round, bool) { ur.mux.Lock() defer ur.mux.Unlock() diff --git a/network/identity/receptionID/store/unknownRounds.go b/network/identity/receptionID/store/unknownRounds.go index d9a6cae07b74b418127c16a59c59f07ce7c1512b..022fd252dba2d7dbaaec14a072e5dbac6623ff25 100644 --- a/network/identity/receptionID/store/unknownRounds.go +++ b/network/identity/receptionID/store/unknownRounds.go @@ -24,13 +24,13 @@ const ( defaultMaxCheck = 3 ) -// UnknownRounds tracks data for unknown rounds -// Should adhere to UnknownRounds interface +// UnknownRounds tracks data for unknown rounds. Should adhere to UnknownRounds +// interface. type UnknownRounds struct { - // Maps an unknown round to how many times the round - // has been checked + // Maps an unknown round to how many times the round has been checked rounds map[id.Round]*uint64 - // Configurations of UnknownRoundStore + + // Configurations of UnknownRounds params UnknownRoundsParams // Key Value store to save data to disk @@ -39,16 +39,17 @@ type UnknownRounds struct { mux sync.Mutex } -// Allows configuration of UnknownRounds parameters +// UnknownRoundsParams allows configuration of UnknownRounds parameters. type UnknownRoundsParams struct { - // Maximum amount of checks of a round - // before that round gets discarded + // MaxChecks is the maximum amount of checks of a round before that round + // gets discarded MaxChecks uint64 - //Determines if the unknown rounds is stored to disk + + // Stored determines if the unknown rounds is stored to disk Stored bool } -// Returns a default set of UnknownRoundsParams +// DefaultUnknownRoundsParams returns a default set of UnknownRoundsParams. func DefaultUnknownRoundsParams() UnknownRoundsParams { return UnknownRoundsParams{ MaxChecks: defaultMaxCheck, @@ -56,23 +57,20 @@ func DefaultUnknownRoundsParams() UnknownRoundsParams { } } -// Build and return new UnknownRounds object +// NewUnknownRounds builds and returns a new UnknownRounds object. func NewUnknownRounds(kv *versioned.KV, params UnknownRoundsParams) *UnknownRounds { urs := newUnknownRounds(kv, params) if err := urs.save(); err != nil { - jww.FATAL.Printf("Failed to store New Unknown Rounds: %+v", err) + jww.FATAL.Printf("Failed to store new UnknownRounds: %+v", err) } return urs } -func newUnknownRounds(kv *versioned.KV, - params UnknownRoundsParams) *UnknownRounds { - // Build the UnmixedMessagesMap - // Modify the prefix of the KV +func newUnknownRounds(kv *versioned.KV, params UnknownRoundsParams) *UnknownRounds { kv = kv.Prefix(unknownRoundPrefix) urs := &UnknownRounds{ @@ -84,7 +82,8 @@ func newUnknownRounds(kv *versioned.KV, return urs } -// LoadUnknownRounds loads the data for a UnknownRoundStore from disk into an object +// LoadUnknownRounds loads the data for a UnknownRounds from disk into an +// object. func LoadUnknownRounds(kv *versioned.KV, params UnknownRoundsParams) *UnknownRounds { kv = kv.Prefix(unknownRoundPrefix) @@ -106,32 +105,33 @@ func LoadUnknownRounds(kv *versioned.KV, return urs } -// Iterate iterates over all rounds. First it runs the -// checker function on the stored rounds: -// If true, it removes from the map and adds to the return slice -// If false, it increments the counter and if it has passed the maxChecks -// in params, it removes from the map -// Afterwards it adds the roundToAdd to the map if an entry isn't present -// Finally it saves the modified map to disk. -// The abandon function can be used to pass the abandoned round somewhere else +// Iterate iterates over all rounds. First it runs the checker function on the +// stored rounds: +// If true, it removes from the map and adds to the return slice. +// If false, it increments the counter and if it has passed the maxChecks in +// params, it removes from the map. +// Afterwards it adds the roundToAdd to the map if an entry isn't present. +// Finally, it saves the modified map to disk. +// The abandon function can be used to pass the abandoned round somewhere else. func (urs *UnknownRounds) Iterate(checker func(rid id.Round) bool, roundsToAdd []id.Round, abandon func(round id.Round)) []id.Round { returnSlice := make([]id.Round, 0) urs.mux.Lock() defer urs.mux.Unlock() + // Check the rounds stored for rnd := range urs.rounds { ok := checker(rnd) if ok { - // If true, Append to the return list and remove from the map + // If true, append to the return list and remove from the map returnSlice = append(returnSlice, rnd) delete(urs.rounds, rnd) } else { // If false, we increment the check counter for that round totalChecks := atomic.AddUint64(urs.rounds[rnd], 1) - // If the round has been checked the maximum amount, - // the rond is removed from the map + // If the round has been checked the maximum amount, then the rond + // is removed from the map if totalChecks > urs.params.MaxChecks { localRnd := rnd go abandon(localRnd) @@ -151,8 +151,7 @@ func (urs *UnknownRounds) Iterate(checker func(rid id.Round) bool, } if err := urs.save(); err != nil { - jww.FATAL.Panicf("Failed to save unknown reounds after "+ - "edit: %+v", err) + jww.FATAL.Panicf("Failed to save unknown rounds after edit: %+v", err) } return returnSlice @@ -172,22 +171,22 @@ func (urs *UnknownRounds) save() error { } // Construct versioning object - obj := versioned.Object{ + obj := &versioned.Object{ Version: unknownRoundsStorageVersion, Timestamp: now, Data: data, } // Save to disk - return urs.kv.Set(unknownRoundsStorageKey, unknownRoundsStorageVersion, &obj) + return urs.kv.Set(unknownRoundsStorageKey, unknownRoundsStorageVersion, obj) } -// save stores the unknown rounds store. func (urs *UnknownRounds) Delete() { urs.mux.Lock() defer urs.mux.Unlock() if urs.params.Stored { - if err := urs.kv.Delete(unknownRoundPrefix, unknownRoundsStorageVersion); err != nil { + err := urs.kv.Delete(unknownRoundPrefix, unknownRoundsStorageVersion) + if err != nil { jww.FATAL.Panicf("Failed to delete unknown rounds: %+v", err) } } @@ -196,18 +195,18 @@ func (urs *UnknownRounds) Delete() { urs.rounds = nil } -// unmarshal loads the serialized round data into the UnknownRounds map +// unmarshal loads the serialized round data into the UnknownRounds map. func (urs *UnknownRounds) unmarshal(b []byte) error { return json.Unmarshal(b, &urs.rounds) } -func (urs *UnknownRounds) Get(round id.Round) (present bool, numchecked uint64) { +func (urs *UnknownRounds) Get(round id.Round) (bool, uint64) { urs.mux.Lock() defer urs.mux.Unlock() - numcheck, exist := urs.rounds[round] + numCheck, exist := urs.rounds[round] if !exist { return false, 0 } - return exist, *numcheck + return exist, *numCheck } diff --git a/network/identity/receptionID/store/unknownRounds_test.go b/network/identity/receptionID/store/unknownRounds_test.go index 9b3fb6317bc84431361623862a0e5eab622c059a..8d7422239eedbfcf81c24174427a985c00a2cba3 100644 --- a/network/identity/receptionID/store/unknownRounds_test.go +++ b/network/identity/receptionID/store/unknownRounds_test.go @@ -19,7 +19,7 @@ import ( ) // Happy path -func TestNewUnknownRoundsStore(t *testing.T) { +func TestNewUnknownRounds(t *testing.T) { kv := versioned.NewKV(make(ekv.Memstore)) expectedStore := &UnknownRounds{ rounds: make(map[id.Round]*uint64), @@ -29,30 +29,30 @@ func TestNewUnknownRoundsStore(t *testing.T) { store := NewUnknownRounds(kv, DefaultUnknownRoundsParams()) - // Compare manually created object with NewUnknownRoundsStore + // Compare manually created object with NewUnknownRounds if !reflect.DeepEqual(expectedStore, store) { - t.Errorf("NewUnknownRoundsStore() returned incorrect Store."+ - "\n\texpected: %+v\n\treceived: %+v", expectedStore, store) + t.Errorf("NewUnknownRounds returned incorrect Store."+ + "\nexpected: %+v\nreceived: %+v", expectedStore, store) } if err := store.save(); err != nil { - t.Fatalf("save() could not write to disk: %v", err) + t.Fatalf("save could not write to disk: %v", err) } expectedData, err := json.Marshal(store.rounds) if err != nil { - t.Fatalf("json.Marshal() produced an error: %v", err) + t.Fatalf("json.Marshal produced an error: %v", err) } key, err := store.kv.Get(unknownRoundsStorageKey, unknownRoundsStorageVersion) if err != nil { - t.Fatalf("get() encoutnered an error when getting Store from KV: %v", err) + t.Fatalf("get encoutnered an error when getting Store from KV: %v", err) } // Check that the stored data is the data outputted by marshal if !bytes.Equal(expectedData, key.Data) { - t.Errorf("NewUnknownRoundsStore() returned incorrect Store."+ - "\n\texpected: %+v\n\treceived: %+v", expectedData, key.Data) + t.Errorf("NewUnknownRounds returned incorrect Store."+ + "\nexpected: %+v\nreceived: %+v", expectedData, key.Data) } } @@ -72,9 +72,9 @@ func TestUnknownRoundsStore_Iterate(t *testing.T) { unknownRounds := make([]id.Round, roundListLen) roundListEven := make([]id.Round, roundListLen) for i := 0; i < roundListLen; i++ { - // Will contain a list of round Ids in range [0,25) + // Will contain a list of round Ids in range [0, 25) unknownRounds[i] = id.Round(i) - // Will contain even round Id's in range [50,100) + // Will contain even round ID's in range [50, 100) roundListEven[i] = id.Round((i + roundListLen) * 2) } @@ -94,29 +94,29 @@ func TestUnknownRoundsStore_Iterate(t *testing.T) { for _, rnd := range received { // Our returned list should contain only even rounds. if uint64(rnd)%2 != 0 { - t.Errorf("Unexpected result from iterate(). "+ + t.Errorf("Unexpected result from iterate. "+ "Round %d should not be in received list", rnd) } + // Elements in the returned list should be deleted from the map. if _, ok := store.rounds[rnd]; ok { - t.Errorf("Returned rounds from iterate should be removed from map"+ - "\n\tFound round %d in map", rnd) + t.Errorf("Returned rounds from iterate should be removed from "+ + "map. Found round %d in map", rnd) } } // Add even round list to map - received = store.Iterate(mockChecker, roundListEven, func(round id.Round) { return }) + received = store.Iterate(mockChecker, roundListEven, func(_ id.Round) {}) if len(received) != 0 { - t.Errorf("Second iteration should return an empty list (no even rounds are left)."+ - "\n\tReturned: %v", received) + t.Errorf("Second iteration should return an empty list (no even "+ + "rounds are left).\nreturned: %v", received) } - // Iterate over map until all rounds have checks incremented over - // maxCheck + // Iterate over map until all rounds have checks incremented over maxCheck for i := 0; i < defaultMaxCheck+1; i++ { - _ = store.Iterate(mockChecker, []id.Round{}, func(round id.Round) { return }) + _ = store.Iterate(mockChecker, []id.Round{}, func(_ id.Round) {}) } @@ -135,7 +135,7 @@ func TestLoadUnknownRoundsStore(t *testing.T) { roundListLen := 25 expectedRounds := make([]id.Round, roundListLen) for i := 0; i < roundListLen; i++ { - // Will contain a list of round Ids in range [0,25) + // Will contain a list of round IDs in range [0, 25) expectedRounds[i] = id.Round(i) } @@ -163,21 +163,21 @@ func TestLoadUnknownRoundsStore(t *testing.T) { if atomic.LoadUint64(check) != 0 { t.Fatalf("Loaded value in map is unexpected."+ - "\n\tExpected: %v"+ - "\n\tReceived: %v", expectedCheckVal, atomic.LoadUint64(check)) + "\nexpected: %v\nreceived: %v", + expectedCheckVal, atomic.LoadUint64(check)) } } - /* Check save used in iterate call */ + // Check save used in iterate call // Check that LoadStore works after iterate call (which implicitly saves) mockChecker := func(round id.Round) bool { return false } - received := store.Iterate(mockChecker, nil, func(round id.Round) { return }) + received := store.Iterate(mockChecker, nil, func(_ id.Round) {}) // Iterate is being called as a dummy, should not return anything if len(received) != 0 { t.Fatalf("Returned list from iterate should not return any rounds."+ - "\n\tReceived: %v", received) + "\nreceived: %v", received) } // Increment check value (iterate will increment all rounds' checked value) @@ -195,8 +195,8 @@ func TestLoadUnknownRoundsStore(t *testing.T) { if atomic.LoadUint64(check) != uint64(expectedCheckVal) { t.Fatalf("Loaded value in map is unexpected."+ - "\n\tExpected: %v"+ - "\n\tReceived: %v", expectedCheckVal, atomic.LoadUint64(check)) + "\nexpected: %v\nreceived: %v", + expectedCheckVal, atomic.LoadUint64(check)) } } diff --git a/network/identity/receptionID/store_test.go b/network/identity/receptionID/store_test.go index cfed1582d80647df8b708558e9082ff0012d6d0f..cf5c4624f72d9c40e311eddd7a9f83d0d3527ecd 100644 --- a/network/identity/receptionID/store_test.go +++ b/network/identity/receptionID/store_test.go @@ -12,14 +12,14 @@ import ( "time" ) -func TestNewStore(t *testing.T) { +func TestNewOrLoadStore_New(t *testing.T) { kv := versioned.NewKV(make(ekv.Memstore)) expected := &Store{ active: make([]*registration, 0), kv: kv, } - s := NewStore(kv) + s := NewOrLoadStore(kv) if !reflect.DeepEqual([]*registration{}, s.active) { t.Errorf("NewStore() failed to return the expected Store."+ @@ -42,9 +42,9 @@ func TestNewStore(t *testing.T) { } } -func TestLoadStore(t *testing.T) { +func TestNewOrLoadStore_Load(t *testing.T) { kv := versioned.NewKV(make(ekv.Memstore)) - s := NewStore(kv) + s := NewOrLoadStore(kv) prng := rand.New(rand.NewSource(42)) // Fill active registration with fake identities @@ -64,7 +64,7 @@ func TestLoadStore(t *testing.T) { t.Errorf("save() produced an error: %+v", err) } - testStore := LoadStore(kv) + testStore := NewOrLoadStore(kv) for i, active := range testStore.active { if !s.active[i].Equal(active.Identity) { t.Errorf("Failed to generate expected Store."+ @@ -75,7 +75,7 @@ func TestLoadStore(t *testing.T) { func TestStore_save(t *testing.T) { kv := versioned.NewKV(make(ekv.Memstore)) - s := NewStore(kv) + s := NewOrLoadStore(kv) prng := rand.New(rand.NewSource(42)) // Fill active registration with fake identities @@ -113,7 +113,7 @@ func TestStore_save(t *testing.T) { } func TestStore_makeStoredReferences(t *testing.T) { - s := NewStore(versioned.NewKV(make(ekv.Memstore))) + s := NewOrLoadStore(versioned.NewKV(make(ekv.Memstore))) prng := rand.New(rand.NewSource(42)) expected := make([]storedReference, 0) @@ -143,7 +143,7 @@ func TestStore_makeStoredReferences(t *testing.T) { func TestStore_GetIdentity(t *testing.T) { kv := versioned.NewKV(make(ekv.Memstore)) - s := NewStore(kv) + s := NewOrLoadStore(kv) prng := rand.New(rand.NewSource(42)) testID, err := generateFakeIdentity(prng, 15, netTime.Now()) if err != nil { @@ -166,7 +166,7 @@ func TestStore_GetIdentity(t *testing.T) { func TestStore_AddIdentity(t *testing.T) { kv := versioned.NewKV(make(ekv.Memstore)) - s := NewStore(kv) + s := NewOrLoadStore(kv) prng := rand.New(rand.NewSource(42)) testID, err := generateFakeIdentity(prng, 15, netTime.Now()) if err != nil { @@ -186,7 +186,7 @@ func TestStore_AddIdentity(t *testing.T) { func TestStore_RemoveIdentity(t *testing.T) { kv := versioned.NewKV(make(ekv.Memstore)) - s := NewStore(kv) + s := NewOrLoadStore(kv) prng := rand.New(rand.NewSource(42)) testID, err := generateFakeIdentity(prng, 15, netTime.Now()) if err != nil { @@ -205,7 +205,7 @@ func TestStore_RemoveIdentity(t *testing.T) { func TestStore_prune(t *testing.T) { kv := versioned.NewKV(make(ekv.Memstore)) - s := NewStore(kv) + s := NewOrLoadStore(kv) prng := rand.New(rand.NewSource(42)) runs := 10 expected := make([]*registration, runs/2) @@ -240,7 +240,7 @@ func TestStore_prune(t *testing.T) { func TestStore_selectIdentity(t *testing.T) { kv := versioned.NewKV(make(ekv.Memstore)) - s := NewStore(kv) + s := NewOrLoadStore(kv) prng := rand.New(rand.NewSource(42)) runs := 10 expectedReg := make([]*registration, runs) diff --git a/network/identity/tracker.go b/network/identity/tracker.go index 202c444728b4a50b251b192c6fceca1859bd5ae5..3d1a34c19fea3446e661051c3750b79fb4ba026b 100644 --- a/network/identity/tracker.go +++ b/network/identity/tracker.go @@ -35,10 +35,13 @@ const addressSpaceSizeChanTag = "ephemeralTracker" var Forever = time.Time{} -const trackedIDChanSize = 1000 -const deleteIDChanSize = 1000 +const ( + trackedIDChanSize = 1000 + deleteIDChanSize = 1000 +) -// DefaultExtraChecks is the default value for ExtraChecks on reception.Identity +// DefaultExtraChecks is the default value for ExtraChecks on +// receptionID.Identity. const DefaultExtraChecks = 10 type Tracker interface { @@ -67,7 +70,7 @@ type trackedID struct { } func NewOrLoadTracker(session storage.Session, addrSpace address.Space) *manager { - //intilization + // Initialization t := &manager{ tracked: make([]trackedID, 0), session: session, @@ -76,30 +79,37 @@ func NewOrLoadTracker(session storage.Session, addrSpace address.Space) *manager addrSpace: addrSpace, mux: &sync.Mutex{}, } - //Load this structure + + // Load this structure err := t.load() if err != nil && os.IsNotExist(err) { - oldTimestamp, err := getOldTimestampStore(t.session) - if err == nil { - jww.WARN.Printf("No tracked identities found, " + - "creating a new tracked identity from legacy stored timestamp") + oldTimestamp, err2 := getOldTimestampStore(t.session) + if err2 == nil { + jww.WARN.Printf("No tracked identities found, creating a new " + + "tracked identity from legacy stored timestamp.") + t.tracked = append(t.tracked, trackedID{ - // make the next generation now so a generation triggers on first run + // Make the next generation now so a generation triggers on + // first run NextGeneration: netTime.Now(), - // it generated previously though oldTimestamp, denote that + // It generated previously though oldTimestamp, denote that LastGeneration: oldTimestamp, Source: t.session.GetReceptionID(), ValidUntil: Forever, Persistent: true, }) } else { - jww.WARN.Printf("No tracked identities found and no legacy stored " + - "timestamp found, creating a new tracked identity from scratch") + jww.WARN.Printf("No tracked identities found and no legacy " + + "stored timestamp found; creating a new tracked identity " + + "from scratch.") + t.tracked = append(t.tracked, trackedID{ - // make the next generation now so a generation triggers on first run + // Make the next generation now so a generation triggers on + // first run NextGeneration: netTime.Now(), - // start generation 24 hours ago to make sure all rescent ephemerals do pickups - // todo: should we go back farther? + // Start generation 24 hours ago to make sure all resent + // ephemeral do pickups + // TODO: Should we go back farther? LastGeneration: netTime.Now().Add(-time.Duration(ephemeral.Period)), Source: t.session.GetReceptionID(), ValidUntil: Forever, @@ -107,7 +117,7 @@ func NewOrLoadTracker(session storage.Session, addrSpace address.Space) *manager }) } } else if err != nil { - jww.FATAL.Panicf("unable to create new Tracker: %+v", err) + jww.FATAL.Panicf("Unable to create new Tracker: %+v", err) } t.store = receptionID.NewOrLoadStore(session.GetKV()) @@ -115,18 +125,19 @@ func NewOrLoadTracker(session storage.Session, addrSpace address.Space) *manager return t } -// Track runs a thread which checks for past and present address ID. -func (tracker manager) StartProcessies() stoppable.Stoppable { +// StartProcessies track runs a thread which checks for past and present address +// ID. +func (t manager) StartProcessies() stoppable.Stoppable { stop := stoppable.NewSingle(ephemeralStoppable) - go tracker.track(stop) + go t.track(stop) return stop } -// AddIdentity adds an identity to be tracked -func (tracker *manager) AddIdentity(id *id.ID, validUntil time.Time, persistent bool) { - tracker.newIdentity <- trackedID{ +// AddIdentity adds an identity to be tracked. +func (t *manager) AddIdentity(id *id.ID, validUntil time.Time, persistent bool) { + t.newIdentity <- trackedID{ NextGeneration: netTime.Now().Add(-time.Second), LastGeneration: time.Time{}, Source: id, @@ -136,66 +147,75 @@ func (tracker *manager) AddIdentity(id *id.ID, validUntil time.Time, persistent } // RemoveIdentity removes a currently tracked identity. -func (tracker *manager) RemoveIdentity(id *id.ID) { - tracker.deleteIdentity <- id +func (t *manager) RemoveIdentity(id *id.ID) { + t.deleteIdentity <- id } // GetEphemeralIdentity returns an ephemeral Identity to poll the network with. -func (tracker *manager) GetEphemeralIdentity(rng io.Reader, addressSize uint8) (receptionID.IdentityUse, error) { - return tracker.store.GetIdentity(rng, addressSize) +func (t *manager) GetEphemeralIdentity(rng io.Reader, addressSize uint8) ( + receptionID.IdentityUse, error) { + return t.store.GetIdentity(rng, addressSize) } -func (tracker *manager) track(stop *stoppable.Single) { +func (t *manager) track(stop *stoppable.Single) { + // Wait until the ID size is retrieved from the network + addressSize := t.addrSpace.GetAddressSpace() - // Wait until we get the ID size from the network - addressSize := tracker.addrSpace.GetAddressSpace() - - /*wait for next event*/ + // Wait for next event trackerLoop: for { edits := false var toRemove map[int]struct{} - nextEvent := tracker.tracked[0].ValidUntil + nextEvent := t.tracked[0].ValidUntil - //loop through every tracked ID and see if any operatrions are needed - for i := range tracker.tracked { - inQuestion := tracker.tracked[i] + // Loop through every tracked ID and see if any operations are needed + for i := range t.tracked { + inQuestion := t.tracked[i] - //generate new ephmerals if is time for it + // Generate new ephemeral if is time for it if netTime.Now().After(inQuestion.NextGeneration) { edits = true - //ensure that ephemerals will not be generated after the identity is invalid + // Ensure that ephemeral IDs will not be generated after the + // identity is invalid generateUntil := inQuestion.NextGeneration - if inQuestion.ValidUntil != Forever && generateUntil.After(inQuestion.ValidUntil) { + if inQuestion.ValidUntil != Forever && + generateUntil.After(inQuestion.ValidUntil) { generateUntil = inQuestion.ValidUntil } - //generate all not yet existing ephemerals - identities, nextNextGeneration := generateIdentitiesOverRange(inQuestion.LastGeneration, - inQuestion.NextGeneration, inQuestion.Source, addressSize) - //add all ephemerals to the ephemeral handler + + // Generate all not yet existing ephemeral IDs + identities, nextNextGeneration := generateIdentitiesOverRange( + inQuestion.LastGeneration, inQuestion.NextGeneration, + inQuestion.Source, addressSize) + + // Add all ephemeral IDs to the ephemeral handler for _, identity := range identities { - // move up the end time if the source identity is invalid before the natural end - // of the ephemeral identity. - if inQuestion.ValidUntil != Forever && identity.End.After(inQuestion.ValidUntil) { + // Move up the end time if the source identity is invalid + // before the natural end of the ephemeral identity + if inQuestion.ValidUntil != Forever && + identity.End.After(inQuestion.ValidUntil) { identity.End = inQuestion.ValidUntil } + identity.Ephemeral = !inQuestion.Persistent - if err := tracker.store.AddIdentity(identity); err != nil { + if err := t.store.AddIdentity(identity); err != nil { jww.FATAL.Panicf("Could not insert identity: %+v", err) } } - //move forward the tracking of when generation should occur + + // Move forward the tracking of when generation should occur inQuestion.LastGeneration = inQuestion.NextGeneration inQuestion.NextGeneration = nextNextGeneration.Add(time.Millisecond) } - // if it is time to delete the id, process the delete - if inQuestion.ValidUntil != Forever && netTime.Now().After(inQuestion.ValidUntil) { + // If it is time to delete the ID, then process the deletion + if inQuestion.ValidUntil != Forever && + netTime.Now().After(inQuestion.ValidUntil) { edits = true toRemove[i] = struct{}{} } else { - // otherwise see if it is responsible for the next event + // Otherwise, see if it is responsible for the next event if inQuestion.NextGeneration.Before(nextEvent) { nextEvent = inQuestion.NextGeneration } @@ -205,57 +225,60 @@ trackerLoop: } } - //process any deletions + // Process any deletions if len(toRemove) > 0 { - newTracked := make([]trackedID, len(tracker.tracked)) - for i := range tracker.tracked { + newTracked := make([]trackedID, 0, len(t.tracked)) + for i := range t.tracked { if _, remove := toRemove[i]; !remove { - newTracked = append(newTracked, tracker.tracked[i]) + newTracked = append(newTracked, t.tracked[i]) } } - tracker.tracked = newTracked + + t.tracked = newTracked } if edits { - tracker.save() + t.save() } - // trigger events early. this will cause generations to happen - // early as well as message pickup. As a result, if there - // are time sync issues between clients and they begin sending - // to ephemerals early, messages will still be picked up + // Trigger events early. This will cause generations to happen early as + // well as message pickup. As a result, if there are time sync issues + // between clients, and they begin sending to ephemeral IDs early, then + // messages will still be picked up. nextUpdate := nextEvent.Add(-validityGracePeriod) // Sleep until the last ID has expired select { case <-time.NewTimer(nextUpdate.Sub(nextUpdate)).C: - case newIdentity := <-tracker.newIdentity: - // if the identity is old, just update its properties - for i := range tracker.tracked { - inQuestion := tracker.tracked[i] + case newIdentity := <-t.newIdentity: + // If the identity is old, then update its properties + for i := range t.tracked { + inQuestion := t.tracked[i] if inQuestion.Source.Cmp(newIdentity.Source) { inQuestion.Persistent = newIdentity.Persistent inQuestion.ValidUntil = newIdentity.ValidUntil - tracker.save() + t.save() continue trackerLoop } } - //otherwise, add it to the list and run - tracker.tracked = append(tracker.tracked, newIdentity) - tracker.save() + + // Otherwise, add it to the list and run + t.tracked = append(t.tracked, newIdentity) + t.save() continue trackerLoop - case deleteID := <-tracker.deleteIdentity: - for i := range tracker.tracked { - inQuestion := tracker.tracked[i] + + case deleteID := <-t.deleteIdentity: + for i := range t.tracked { + inQuestion := t.tracked[i] if inQuestion.Source.Cmp(deleteID) { - tracker.tracked = append(tracker.tracked[:i], tracker.tracked[i+1:]...) - tracker.save() - tracker.store.RemoveIdentities(deleteID) + t.tracked = append(t.tracked[:i], t.tracked[i+1:]...) + t.save() + t.store.RemoveIdentities(deleteID) break } } case <-stop.Quit(): - tracker.addrSpace.UnregisterAddressSpaceNotification(addressSpaceSizeChanTag) + t.addrSpace.UnregisterAddressSpaceNotification(addressSpaceSizeChanTag) stop.ToStopped() return } @@ -284,12 +307,12 @@ func unmarshalTimestamp(lastTimestampObj *versioned.Object) (time.Time, error) { func generateIdentitiesOverRange(lastGeneration, generateThrough time.Time, source *id.ID, addressSize uint8) ([]receptionID.Identity, time.Time) { - protoIds, err := ephemeral.GetIdsByRange( - source, uint(addressSize), lastGeneration, generateThrough.Sub(lastGeneration)) + protoIds, err := ephemeral.GetIdsByRange(source, uint(addressSize), + lastGeneration, generateThrough.Sub(lastGeneration)) jww.DEBUG.Printf("Now: %s, LastCheck: %s, Different: %s", generateThrough, generateThrough, generateThrough.Sub(lastGeneration)) - jww.DEBUG.Printf("protoIds Count: %d", len(protoIds)) + jww.DEBUG.Printf("protoIds count: %d", len(protoIds)) if err != nil { jww.FATAL.Panicf("Could not generate upcoming IDs: %+v", err) @@ -316,7 +339,7 @@ func generateIdentitiesOverRange(lastGeneration, generateThrough time.Time, } - jww.INFO.Printf("Number of Identities Generated: %d", len(identities)) + jww.INFO.Printf("Number of identities generated: %d", len(identities)) jww.INFO.Printf("Current Identity: %d (source: %s), Start: %s, End: %s", identities[len(identities)-1].EphId.Int64(), identities[len(identities)-1].Source, @@ -326,24 +349,24 @@ func generateIdentitiesOverRange(lastGeneration, generateThrough time.Time, return identities, identities[len(identities)-1].End } -func (tracker *manager) save() { - tracker.mux.Lock() - defer tracker.mux.Unlock() - persistant := make([]trackedID, 0, len(tracker.tracked)) +func (t *manager) save() { + t.mux.Lock() + defer t.mux.Unlock() + persistent := make([]trackedID, 0, len(t.tracked)) - for i := range tracker.tracked { - if tracker.tracked[i].Persistent { - persistant = append(persistant, tracker.tracked[i]) + for i := range t.tracked { + if t.tracked[i].Persistent { + persistent = append(persistent, t.tracked[i]) } } - if len(persistant) == 0 { + if len(persistent) == 0 { return } - data, err := json.Marshal(&persistant) + data, err := json.Marshal(&persistent) if err != nil { - jww.FATAL.Panicf("unable to marshal trackedID list: %+v", err) + jww.FATAL.Panicf("Unable to marshal trackedID list: %+v", err) } obj := &versioned.Object{ @@ -352,10 +375,9 @@ func (tracker *manager) save() { Data: data, } - err = tracker.session.GetKV().Set(TrackerListKey, TrackerListVersion, - obj) + err = t.session.GetKV().Set(TrackerListKey, TrackerListVersion, obj) if err != nil { - jww.FATAL.Panicf("unable to save trackedID list: %+v", err) + jww.FATAL.Panicf("Unable to save trackedID list: %+v", err) } }