1777 lines
68 KiB
Go
1777 lines
68 KiB
Go
|
|
// networkJobs provides functions to perform network jobs
|
|
// An example is downloading a user's inbox messages
|
|
// All of these jobs are run in the background by backgroundJobs (see backgroundJobs.go)
|
|
|
|
package networkJobs
|
|
|
|
//TODO: Add all of these jobs to backgroundJobs.go
|
|
|
|
//TODO: Implement these network jobs:
|
|
|
|
// Download message funded statuses for hosting
|
|
// Download message funded statuses for moderation
|
|
// Download message funded statuses for reading (this is to make sure messages we have received are funded)
|
|
// Download Host identity funded statuses
|
|
// Download Mate identity/profile funded statuses for hosting
|
|
// Download Mate identity/profile funded statuses for moderation
|
|
// Download Mate identity/profile funded statuses for browsing
|
|
// Download Mate identity/profile funded statuses for contacts/chat recipients
|
|
// Download report funded statuses for hosting
|
|
// Download report funded statuses for moderation
|
|
// Broadcast my Mate profile
|
|
// Broadcast my Host profile
|
|
// Broadcast my Moderator profile/reviews
|
|
// Broadcast my Mate messages
|
|
// Broadcast my Moderator messages
|
|
|
|
// Update Existing Mate User Profiles
|
|
// -We need a way for a client to user know if another user has changed their profile to no longer fulfill our downloads criteria
|
|
// -We need to download updated profiles for specific identities, without providing a Criteria in the request
|
|
// -We should download the newest viewable profile for all Mate users whose stored profile fulfills our criteria.
|
|
// -If the user's newer downloaded profile does not fulfill our criteria, we should delete their old profiles.
|
|
|
|
//TODO: More jobs
|
|
|
|
//TODO: Add limits to the number of hosts per job, and the number of items per request
|
|
// Otherwise, some of these jobs could take a very long time to complete, due to the number of hosts being contacted.
|
|
|
|
//TODO: The Mate outlier lists can be reduced by removing all of the mate outliers whose profiles/viewable statuses will be downloaded by other jobs.
|
|
|
|
import "seekia/internal/byteRange"
|
|
import "seekia/internal/badgerDatabase"
|
|
import "seekia/internal/contentMetadata"
|
|
import "seekia/internal/desires/myMateDesires"
|
|
import "seekia/internal/helpers"
|
|
import "seekia/internal/logger"
|
|
import "seekia/internal/messaging/myChatMessages"
|
|
import "seekia/internal/messaging/myInbox"
|
|
import "seekia/internal/messaging/peerChatKeys"
|
|
import "seekia/internal/moderation/myReviews"
|
|
import "seekia/internal/myBlockedUsers"
|
|
import "seekia/internal/myContacts"
|
|
import "seekia/internal/myIdentity"
|
|
import "seekia/internal/myLikedUsers"
|
|
import "seekia/internal/myRanges"
|
|
import "seekia/internal/mySettings"
|
|
import "seekia/internal/network/fundedStatus"
|
|
import "seekia/internal/network/mateCriteria"
|
|
import "seekia/internal/network/myMateCriteria"
|
|
import "seekia/internal/network/queryHosts"
|
|
import "seekia/internal/profiles/calculatedAttributes"
|
|
import "seekia/internal/profiles/profileStorage"
|
|
import "seekia/internal/profiles/readProfiles"
|
|
import "seekia/internal/profiles/viewableProfiles"
|
|
|
|
import "errors"
|
|
|
|
// This function will download and update the network-wide parameters files
|
|
func DownloadParameters(networkType byte)error{
|
|
|
|
isValid := helpers.VerifyNetworkType(networkType)
|
|
if (isValid == false){
|
|
networkTypeString := helpers.ConvertByteToString(networkType)
|
|
return errors.New("DownloadParameters called with invalid networkType: " + networkTypeString)
|
|
}
|
|
|
|
err := queryHosts.DownloadParametersFromHosts(true, networkType, 5)
|
|
if (err != nil) { return err }
|
|
|
|
return nil
|
|
}
|
|
|
|
// This function will download all of the network's newest viewable host/moderator profiles
|
|
// -This is used by all users to download host profiles
|
|
// -Users will only connect to Viewable hosts, whom are not banned
|
|
// -This is used by moderators/hosts to download all moderator profiles
|
|
// All hosts/moderators must download all newest viewable Moderator profiles
|
|
func DownloadAllNewestViewableUserProfiles(profileType string, networkType byte)error{
|
|
|
|
isValid := helpers.VerifyNetworkType(networkType)
|
|
if (isValid == false){
|
|
networkTypeString := helpers.ConvertByteToString(networkType)
|
|
return errors.New("DownloadAllNewestViewableUserProfiles called with invalid networkType: " + networkTypeString)
|
|
}
|
|
|
|
// This functions is not used for Mate profiles
|
|
// Mate profiles are always downloaded based on a range, whereas in this function, we download all newest viewable profiles.
|
|
|
|
if (profileType != "Host" && profileType != "Moderator"){
|
|
return errors.New("DownloadAllNewestViewableUserProfiles called with invalid profileType: " + profileType)
|
|
}
|
|
|
|
checkIfProfileShouldBeDownloaded := func(_ [28]byte, profileAuthor [16]byte, profileCreationTime int64)(bool, error){
|
|
|
|
// Check to see if our newest profile is older than the received profile
|
|
|
|
newestViewableProfileExists, _, _, _, storedProfileCreationTime, _, err := viewableProfiles.GetNewestViewableUserProfile(profileAuthor, networkType, true, false, true)
|
|
if (err != nil) { return false, err }
|
|
if (newestViewableProfileExists == false){
|
|
// We do not have any viewable profiles for this host
|
|
// Download this profile
|
|
return true, nil
|
|
}
|
|
|
|
if (profileCreationTime <= storedProfileCreationTime){
|
|
// Host we are retrieving from has a profile that is not newer than our existing profile
|
|
// We can skip this profile
|
|
return false, nil
|
|
}
|
|
|
|
// This profile is newer than our existing newest viewable profile
|
|
// We download it.
|
|
return true, nil
|
|
}
|
|
|
|
minimumRange, maximumRange := byteRange.GetMinimumMaximumIdentityHashBounds()
|
|
|
|
emptyList := make([][16]byte, 0)
|
|
|
|
err := queryHosts.DownloadProfilesFromHosts(false, networkType, profileType, minimumRange, maximumRange, emptyList, nil, true, true, false, checkIfProfileShouldBeDownloaded, 10)
|
|
if (err != nil) { return err }
|
|
|
|
return nil
|
|
}
|
|
|
|
// This function will download newest viewable mate profiles that fulfill user's downloads criteria
|
|
// It is used by users who are downloading profiles to find matches.
|
|
func DownloadMateProfilesToBrowse(networkType byte)error{
|
|
|
|
isValid := helpers.VerifyNetworkType(networkType)
|
|
if (isValid == false){
|
|
networkTypeString := helpers.ConvertByteToString(networkType)
|
|
return errors.New("DownloadMateProfilesToBrowse called with invalid networkType: " + networkTypeString)
|
|
}
|
|
|
|
minimumRange, maximumRange := byteRange.GetMinimumMaximumIdentityHashBounds()
|
|
|
|
getMyCriteria := func()([]byte, error){
|
|
|
|
exists, myCriteria, err := myMateCriteria.GetMyMateDownloadsCriteria()
|
|
if (err != nil) { return nil, err }
|
|
if (exists == false){
|
|
return nil, nil
|
|
}
|
|
return myCriteria, nil
|
|
}
|
|
|
|
myCriteria, err := getMyCriteria()
|
|
if (err != nil) { return err }
|
|
|
|
getDownloadAllBool := func()(bool, error){
|
|
|
|
//TODO: Fix below
|
|
desiresPruningMode := false
|
|
|
|
if (desiresPruningMode == true){
|
|
return true, nil
|
|
}
|
|
|
|
return false, nil
|
|
}
|
|
|
|
downloadAllBool, err := getDownloadAllBool()
|
|
if (err != nil) { return err }
|
|
|
|
emptyList := make([][16]byte, 0)
|
|
|
|
checkIfProfileShouldBeDownloaded := func(_ [28]byte, profileAuthor [16]byte, profileCreationTime int64)(bool, error){
|
|
// This function is only called if profile hash is not already downloaded
|
|
// We check if we have a profile that is newer (and viewable)
|
|
// If we have a newer viewable profile, we will skip downloading this profile
|
|
|
|
// We wont check, but if we have a newer profile that is not known to be viewable, we will still download this profile
|
|
// We will delete this older profile if and when the newer profile becomes viewable
|
|
|
|
profileExists, _, _, _, storedProfileCreationTime, _, err := viewableProfiles.GetNewestViewableUserProfile(profileAuthor, networkType, true, false, true)
|
|
if (err != nil) { return false, err }
|
|
if (profileExists == false){
|
|
return true, nil
|
|
}
|
|
|
|
if (storedProfileCreationTime >= profileCreationTime){
|
|
// The profile the host is offering is not newer than our existing
|
|
// We will skip it
|
|
|
|
return false, nil
|
|
}
|
|
|
|
// Profile is newer than the profile we already have, or we dont have any profile for this identity
|
|
// We will download it
|
|
return true, nil
|
|
}
|
|
|
|
err = queryHosts.DownloadProfilesFromHosts(false, networkType, "Mate", minimumRange, maximumRange, emptyList, myCriteria, true, true, downloadAllBool, checkIfProfileShouldBeDownloaded, 10)
|
|
if (err != nil) { return err }
|
|
|
|
return nil
|
|
}
|
|
|
|
// This function will download the newest viewable profiles for a user's mate outliers
|
|
// Outliers are either contacts, likes, or chat recipients.
|
|
// We download them so the user's client will have their profiles downloaded, even if the users do not fulfill our criteria
|
|
// This is done so that a user's client has the profiles for users within their contacts and users whom they are chatting with
|
|
// These are downloaded one-by-one to prevent hosts from learning a user's contacts/likes/chat recipients
|
|
func DownloadMateOutlierProfiles(outlierType string, networkType byte, missingOrExisting string)error{
|
|
|
|
if (outlierType != "Contacts" && outlierType != "Likes" && outlierType != "ChatRecipients"){
|
|
return errors.New("DownloadMateOutlierProfiles called with invalid outlierType: " + outlierType)
|
|
}
|
|
|
|
isValid := helpers.VerifyNetworkType(networkType)
|
|
if (isValid == false){
|
|
networkTypeString := helpers.ConvertByteToString(networkType)
|
|
return errors.New("DownloadMateOutlierProfiles called with invalid networkType: " + networkTypeString)
|
|
}
|
|
|
|
if (missingOrExisting != "Missing" && missingOrExisting != "Existing"){
|
|
return errors.New("DownloadMateOutlierProfiles called with invalid missingOrExisting: " + missingOrExisting)
|
|
}
|
|
|
|
//Outputs:
|
|
// -[][16]byte: List of identities
|
|
// -error
|
|
getMyOutlierIdentitiesList := func()([][16]byte, error){
|
|
|
|
if (outlierType == "Contacts"){
|
|
|
|
myContactIdentityHashesList, err := myContacts.GetMyContactsList("Mate")
|
|
if (err != nil) { return nil, err }
|
|
|
|
return myContactIdentityHashesList, nil
|
|
}
|
|
if (outlierType == "Likes"){
|
|
|
|
myLikedUsersList, err := myLikedUsers.GetMyLikedUsersList()
|
|
if (err != nil) { return nil, err }
|
|
|
|
return myLikedUsersList, nil
|
|
}
|
|
|
|
myIdentityExists, chatRecipientIdentityHashesList, err := myChatMessages.GetAllMyNonBlockedChatRecipients("Mate", networkType)
|
|
if (err != nil) { return nil, err }
|
|
if (myIdentityExists == false){
|
|
// Nothing to do, mate identity does not exist
|
|
emptyList := make([][16]byte, 0)
|
|
return emptyList, nil
|
|
}
|
|
|
|
return chatRecipientIdentityHashesList, nil
|
|
}
|
|
|
|
myOutlierIdentitiesList, err := getMyOutlierIdentitiesList()
|
|
if (err != nil) { return err }
|
|
if (len(myOutlierIdentitiesList) == 0){
|
|
return nil
|
|
}
|
|
|
|
helpers.RandomizeListOrder(myOutlierIdentitiesList)
|
|
|
|
// We will attempt to retrieve the newest viewable profiles for the identities
|
|
|
|
for _, userIdentityHash := range myOutlierIdentitiesList{
|
|
|
|
statusIsKnown, identityIsFunded, err := fundedStatus.GetIdentityIsFundedStatus(userIdentityHash, networkType)
|
|
if (err != nil) { return err }
|
|
if (statusIsKnown == true && identityIsFunded == false){
|
|
|
|
// The user's identity not funded
|
|
// This means that none of their profiles will be hosted by the network
|
|
// We will not try to download their profile, because it will not exist on the network
|
|
continue
|
|
}
|
|
|
|
// We check to see if the user's active chat keys exist
|
|
// We do this because even if a user's profile exists, it may not contain the user's newest chat keys
|
|
|
|
keysAreMissing, err := peerChatKeys.CheckIfUsersChatKeysAreMissing(userIdentityHash, networkType)
|
|
if (err != nil) { return err }
|
|
if (keysAreMissing == true){
|
|
if (missingOrExisting == "Existing"){
|
|
continue
|
|
}
|
|
}
|
|
|
|
profileExists, _, _, _, _, _, err := viewableProfiles.GetNewestViewableUserProfile(userIdentityHash, networkType, true, false, true)
|
|
if (err != nil) { return err }
|
|
if (profileExists == false){
|
|
|
|
if (missingOrExisting == "Existing"){
|
|
continue
|
|
}
|
|
} else {
|
|
if (missingOrExisting == "Missing"){
|
|
continue
|
|
}
|
|
}
|
|
|
|
checkIfProfileShouldBeDownloaded := func(_ [28]byte, profileAuthor [16]byte, profileCreationTime int64)(bool, error){
|
|
|
|
// We check to see if this profile is newer than our stored newest viewable profile for the identity
|
|
// If it is, we download the profile
|
|
|
|
profileExists, _, _, _, existingProfileCreationTime, _, err := viewableProfiles.GetNewestViewableUserProfile(profileAuthor, networkType, true, false, true)
|
|
if (err != nil) { return false, err }
|
|
if (profileExists == false){
|
|
return true, nil
|
|
}
|
|
|
|
if (profileCreationTime <= existingProfileCreationTime){
|
|
return false, nil
|
|
}
|
|
|
|
return true, nil
|
|
}
|
|
|
|
identitiesList := [][16]byte{userIdentityHash}
|
|
|
|
minimumRange, maximumRange := byteRange.GetMinimumMaximumIdentityHashBounds()
|
|
|
|
err = queryHosts.DownloadProfilesFromHosts(true, networkType, "Mate", minimumRange, maximumRange, identitiesList, nil, true, true, false, checkIfProfileShouldBeDownloaded, 1)
|
|
if (err != nil) { return err }
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// This function will download profiles within our host range
|
|
// This should be called if a user is in Host mode.
|
|
func DownloadProfilesToHost(profileType string, networkType byte)error{
|
|
|
|
if (profileType != "Mate" && profileType != "Host" && profileType != "Moderator"){
|
|
return errors.New("DownloadProfilesToHost called with invalid profileType: " + profileType)
|
|
}
|
|
|
|
isValid := helpers.VerifyNetworkType(networkType)
|
|
if (isValid == false){
|
|
networkTypeString := helpers.ConvertByteToString(networkType)
|
|
return errors.New("DownloadProfilesToHost called with invalid networkType: " + networkTypeString)
|
|
}
|
|
|
|
hostModeEnabled, hostingAny, myIdentitiesToHostRangeStart, myIdentitiesToHostRangeEnd, err := myRanges.GetMyIdentitiesToHostRange(profileType)
|
|
if (err != nil) { return err }
|
|
if (hostModeEnabled == false){
|
|
|
|
// Host mode must have been turned off recently.
|
|
|
|
err := logger.AddLogEntry("Network", "DownloadProfilesToHost called when Host mode is disabled.")
|
|
if (err != nil) { return err }
|
|
|
|
return nil
|
|
}
|
|
if (hostingAny == false) {
|
|
// No profiles to host of this profileType. Nothing to do.
|
|
return nil
|
|
}
|
|
|
|
checkIfProfileShouldBeDownloaded := func(profileHash [28]byte, profileAuthor [16]byte, profileCreationTime int64)(bool, error){
|
|
|
|
//TODO
|
|
|
|
// First we check the moderator consensus of the identity
|
|
// If consensus is ban, we will only download profile if time it has been banned is not older than maximum time to store banned content
|
|
|
|
// Then we check to see if we have profile metadata
|
|
// If we don't, we download the profile.
|
|
|
|
// At this point, we have the profile metadata but not the profile
|
|
// That means we thought it was worth deleting at one point (or it was downloaded for mate/moderator reasons)
|
|
|
|
// Then we check the moderator consensus of profile
|
|
// If consensus is ban, we will only download profile if time it has been banned is not older than maximum time to store banned content
|
|
// Otherwise, we will not download profile
|
|
|
|
// At this point, consensus for profile is approve/none and identity is not banned
|
|
// We then check to see if we have a newer profile by the same identity
|
|
// If there is no newer profile, we download the profile
|
|
|
|
// At this point, there is a newer profile for the identity
|
|
// We only want to download this older profile if it can be used by moderators to determine if the identity should be banned
|
|
// We dont want this to be abused, if an attacker created a report for many old profiles that existed on the network, they could cause hosts to download all those old profiles
|
|
// So, if profile has been approved for a long enough period of time, it does not need to be hosted anymore
|
|
// We cannot trust the creationTimes for reviews, reports, or profiles, so each host keeps track of the time that a consensus has existed based on the reviews it has downloaded
|
|
// We use verdictHistory for this
|
|
|
|
// If offered profile is approved, we check to see if profile has been approved for at least the maximum time to store old approved profiles
|
|
// If it has been approved for at least that long, we will not download the profile
|
|
// If it has been approved but not for that long, we will download the profile, just so that moderators can determine if consensus is wrong before profile is dropped from network
|
|
|
|
// At this point, consensus for profile is none, and it is not the user's newest profile
|
|
// We check to see if any ban reviews and reports exist for the profile
|
|
|
|
// If there are any ban reviews or reports, we check to see how long time that consensus has been none.
|
|
// If that time is older than maximum time to store banned and reported no consensus old content, we will not download it
|
|
// If that time has not passed, we will download the profile
|
|
|
|
// At this point, the profile has no ban reviews/reports and consensus is none
|
|
// We will check if profile's no consensus time is older than maximum time to store unreported and unbanned no consensus old content
|
|
// If the profile is older than that time, we will not download it
|
|
// If the profile is newer than that time, we will download it
|
|
|
|
// This is quite complicated and could be simplified
|
|
// Basically, we want to profiles on the network for long enough so the moderators can review them and ban any moderators who wrongly banned/approved them
|
|
|
|
return true, nil
|
|
}
|
|
|
|
getGetViewableProfilesOnlyBool := func()(bool, error){
|
|
|
|
if (profileType == "Host"){
|
|
// Hosts must download all peer host profiles, regardless of viewable status
|
|
// This is because (a) malicious moderator(s) could ban all Host profiles and cripple the network
|
|
// Host profiles have no images, so they are much less legally risky to download anyway.
|
|
//TODO: Make it clear in the GUI that hosts will host all unviewable host profiles, even if HostUnviewableProfiles is disabled.
|
|
return false, nil
|
|
}
|
|
|
|
exists, hostUnviewableStatus, err := mySettings.GetSetting("HostUnviewableProfilesOnOffStatus")
|
|
if (err != nil) { return false, err }
|
|
if (exists == true && hostUnviewableStatus == "On") {
|
|
return false, nil
|
|
}
|
|
return true, nil
|
|
}
|
|
|
|
getViewableProfilesOnlyBool, err := getGetViewableProfilesOnlyBool()
|
|
if (err != nil) { return err }
|
|
|
|
emptyList := make([][16]byte, 0)
|
|
|
|
err = queryHosts.DownloadProfilesFromHosts(true, networkType, profileType, myIdentitiesToHostRangeStart, myIdentitiesToHostRangeEnd, emptyList, nil, false, getViewableProfilesOnlyBool, false, checkIfProfileShouldBeDownloaded, 10)
|
|
if (err != nil) { return err }
|
|
|
|
return nil
|
|
}
|
|
|
|
|
|
// This function will download profiles within our moderation range
|
|
func DownloadProfilesToModerate(profileType string, networkType byte)error{
|
|
|
|
if (profileType != "Mate" && profileType != "Host" && profileType != "Moderator"){
|
|
return errors.New("DownloadProfilesToModerate called with invalid profileType: " + profileType)
|
|
}
|
|
|
|
isValid := helpers.VerifyNetworkType(networkType)
|
|
if (isValid == false){
|
|
networkTypeString := helpers.ConvertByteToString(networkType)
|
|
return errors.New("DownloadProfilesToModerate called with invalid networkType: " + networkTypeString)
|
|
}
|
|
|
|
moderatorModeEnabled, moderatingAny, myIdentitiesToModerateRangeStart, myIdentitiesToModerateRangeEnd, err := myRanges.GetMyIdentitiesToModerateRange(profileType)
|
|
if (err != nil) { return err }
|
|
if (moderatorModeEnabled == false){
|
|
|
|
// This should not happen unless moderator mode was turned off recently
|
|
err := logger.AddLogEntry("Network", "DownloadProfilesToModerate called when moderator mode is disabled.")
|
|
if (err != nil) { return err }
|
|
|
|
return nil
|
|
}
|
|
if (moderatingAny == false){
|
|
// We are not moderating any profiles
|
|
return nil
|
|
}
|
|
|
|
checkIfProfileShouldBeDownloaded := func(profileHash [28]byte, profileIdentityHash [16]byte, profileCreationTime int64)(bool, error){
|
|
|
|
//TODO: See if we have already reviewed the profile, if yes, then we don't need to download it.
|
|
// Also, if we have the profile's metadata, and it is not the user's newest profile, and it has no ban reviews, we don't need to download it.
|
|
// We must have the profile metadata downloaded because it is the only way we can be sure the profile has no ban reviews
|
|
|
|
return true, nil
|
|
}
|
|
|
|
emptyList := make([][16]byte, 0)
|
|
|
|
err = queryHosts.DownloadProfilesFromHosts(true, networkType, profileType, myIdentitiesToModerateRangeStart, myIdentitiesToModerateRangeEnd, emptyList, nil, false, false, false, checkIfProfileShouldBeDownloaded, 10)
|
|
if (err != nil) { return err }
|
|
|
|
return nil
|
|
}
|
|
|
|
|
|
// This function will download messages in our inboxes
|
|
// Each inbox has to be queried seperately from a different host to prevent linking the inboxes together
|
|
func DownloadMyInboxMessages(identityType string, networkType byte)error{
|
|
|
|
if (identityType != "Mate" && identityType != "Moderator"){
|
|
return errors.New("DownloadMyInboxMessages called with invalid identityType: " + identityType)
|
|
}
|
|
|
|
isValid := helpers.VerifyNetworkType(networkType)
|
|
if (isValid == false){
|
|
networkTypeString := helpers.ConvertByteToString(networkType)
|
|
return errors.New("DownloadMyInboxMessages called with invalid networkType: " + networkTypeString)
|
|
}
|
|
|
|
myIdentityFound, myIdentityHash, err := myIdentity.GetMyIdentityHash(identityType)
|
|
if (err != nil) { return err }
|
|
if (myIdentityFound == false){
|
|
return nil
|
|
}
|
|
|
|
myInboxesList, err := myInbox.GetAllMyActiveInboxes(myIdentityHash, networkType)
|
|
if (err != nil) { return err }
|
|
|
|
helpers.RandomizeListOrder(myInboxesList)
|
|
|
|
minimumInboxRange, maximumInboxRange := byteRange.GetMinimumMaximumInboxBounds()
|
|
|
|
for _, inbox := range myInboxesList{
|
|
|
|
inboxAsList := [][10]byte{inbox}
|
|
|
|
checkIfMessageShouldBeDownloaded := func(messageHash [26]byte)(bool, error){
|
|
|
|
metadataExists, _, messageNetworkType, _, messageInbox, _, err := contentMetadata.GetMessageMetadata(messageHash)
|
|
if (err != nil) { return false, err }
|
|
if (metadataExists == false){
|
|
return true, nil
|
|
}
|
|
// We already downloaded the message at some point
|
|
// First we see if the message inbox/networkType matches what we requested
|
|
|
|
if (messageNetworkType != networkType || messageInbox != inbox){
|
|
// The host is offering us a message we know does not belong to the inbox/networkType we requested
|
|
// The host is malicious.
|
|
|
|
// We download the message so they do not learn that we downloaded this message at one point (to prevent fingerprinting)
|
|
|
|
// We should have already checked for this within queryHosts.DownloadMessagesFromHosts
|
|
// The only way we would not have known is if we downloaded the message recently
|
|
err := logger.AddLogEntry("Network", "checkIfMessageShouldBeDownloaded called when inbox/networkType does not match message we have metadata for.")
|
|
if (err != nil) { return false, err }
|
|
|
|
return true, nil
|
|
}
|
|
|
|
// Now we check to see if we have already imported, deleted, or failed to decrypt the message
|
|
|
|
isDeleted, err := myChatMessages.CheckIfMessageIsDeleted(messageHash)
|
|
if (err != nil) { return false, err }
|
|
if (isDeleted == true){
|
|
return false, nil
|
|
}
|
|
|
|
isUndecryptable, err := myChatMessages.CheckIfMessageIsUndecryptable(messageHash)
|
|
if (err != nil) { return false, err }
|
|
if (isUndecryptable == true){
|
|
return false, nil
|
|
}
|
|
|
|
isImported, err := myChatMessages.CheckIfMessageIsImported(messageHash, identityType, messageNetworkType)
|
|
if (err != nil) { return false, err }
|
|
if (isImported == true){
|
|
return false, nil
|
|
}
|
|
|
|
return true, nil
|
|
}
|
|
|
|
err := queryHosts.DownloadMessagesFromHosts(false, networkType, minimumInboxRange, maximumInboxRange, inboxAsList, false, false, checkIfMessageShouldBeDownloaded, 1)
|
|
if (err != nil) { return err }
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// This function will download messages within our hosting range
|
|
// This should be called periodically if we are in Host mode
|
|
func DownloadMessagesToHost(networkType byte)error{
|
|
|
|
isValid := helpers.VerifyNetworkType(networkType)
|
|
if (isValid == false){
|
|
networkTypeString := helpers.ConvertByteToString(networkType)
|
|
return errors.New("DownloadMessagesToHost called with invalid networkType: " + networkTypeString)
|
|
}
|
|
|
|
hostModeEnabled, hostingAny, myInboxRangeStart, myInboxRangeEnd, err := myRanges.GetMyInboxesToHostRange()
|
|
if (err != nil) { return err }
|
|
if (hostModeEnabled == false){
|
|
// Host mode is disabled. Nothing to do.
|
|
// This should not happen unless host mode was turned off recently
|
|
err := logger.AddLogEntry("Network", "DownloadMessagesToHost called when Host mode is disabled.")
|
|
if (err != nil) { return err }
|
|
|
|
return nil
|
|
}
|
|
if (hostingAny == false){
|
|
// Not hosting any messages. Nothing to do.
|
|
return nil
|
|
}
|
|
|
|
// We are not retrieving based on a list of inboxes
|
|
inboxesToRetrieveList := make([][10]byte, 0)
|
|
|
|
getGetViewableMessagesOnlyBool := func()(bool, error){
|
|
|
|
exists, hostUnviewableStatus, err := mySettings.GetSetting("HostUnviewableMessagesOnOffStatus")
|
|
if (err != nil) { return false, err }
|
|
if (exists == true && hostUnviewableStatus == "On") {
|
|
return false, nil
|
|
}
|
|
|
|
return true, nil
|
|
}
|
|
|
|
getViewableMessagesOnlyBool, err := getGetViewableMessagesOnlyBool()
|
|
if (err != nil) { return err }
|
|
|
|
checkIfMessageShouldBeDownloaded := func(inputMessageHash [26]byte)(bool, error){
|
|
|
|
//TODO:
|
|
// This should be similar to the function in DownloadProfilesToHost
|
|
|
|
return true, nil
|
|
}
|
|
|
|
err = queryHosts.DownloadMessagesFromHosts(true, networkType, myInboxRangeStart, myInboxRangeEnd, inboxesToRetrieveList, getViewableMessagesOnlyBool, false, checkIfMessageShouldBeDownloaded, 5)
|
|
if (err != nil) { return err }
|
|
|
|
return nil
|
|
}
|
|
|
|
|
|
// This function will download messages within our moderation range
|
|
// This should be called periodically if the user is in Moderator mode.
|
|
func DownloadMessagesToModerate(networkType byte)error{
|
|
|
|
isValid := helpers.VerifyNetworkType(networkType)
|
|
if (isValid == false){
|
|
networkTypeString := helpers.ConvertByteToString(networkType)
|
|
return errors.New("DownloadMessagesToModerate called with invalid networkType: " + networkTypeString)
|
|
}
|
|
|
|
moderatorModeEnabled, moderatingAny, myInboxRangeStart, myInboxRangeEnd, err := myRanges.GetMyInboxesToModerateRange()
|
|
if (err != nil) { return err }
|
|
if (moderatorModeEnabled == false){
|
|
// User must have disabled moderator mode recently
|
|
err := logger.AddLogEntry("Network", "DownloadMessagesToModerate called when user is not in Moderator mode.")
|
|
if (err != nil) { return err }
|
|
|
|
return nil
|
|
}
|
|
if (moderatingAny == false){
|
|
// We are not moderating any messages.
|
|
|
|
return nil
|
|
}
|
|
|
|
checkIfMessageShouldBeDownloaded := func(inputMessageHash [26]byte)(bool, error){
|
|
|
|
// This function is only called if we don't already have the message downloaded
|
|
|
|
metadataExists, _, messageNetworkType, _, messageInbox, _, err := contentMetadata.GetMessageMetadata(inputMessageHash)
|
|
if (err != nil) { return false, err }
|
|
if (metadataExists == false){
|
|
return true, nil
|
|
}
|
|
if (messageNetworkType != networkType){
|
|
// The host is offering us a message we know does not belong to the networkType we requested
|
|
// The host is malicious.
|
|
|
|
// We download the message so they do not learn that we downloaded this message at one point (to prevent fingerprinting)
|
|
|
|
return true, nil
|
|
}
|
|
|
|
isWithinRequestRange, err := byteRange.CheckIfInboxIsWithinRange(myInboxRangeStart, myInboxRangeEnd, messageInbox)
|
|
if (err != nil) { return false, err }
|
|
if (isWithinRequestRange == false){
|
|
// The host is offering us a message we know does not belong to the inbox range we requested
|
|
// The host is malicious.
|
|
|
|
// We download the message so they do not learn that we downloaded this message at one point (to prevent fingerprinting)
|
|
|
|
return true, nil
|
|
}
|
|
|
|
myIdentityExists, messageMetadataIsKnown, iHaveReviewed, _, err := myReviews.GetMyNewestMessageModerationVerdict(inputMessageHash)
|
|
if (err != nil) { return false, err }
|
|
if (myIdentityExists == false){
|
|
// Without an identity, we would only use moderator mode to browse content
|
|
// We should therefore download the message
|
|
return true, nil
|
|
}
|
|
if (messageMetadataIsKnown == false){
|
|
// We must have just deleted our message metadata
|
|
//TODO: Log this
|
|
return true, nil
|
|
}
|
|
if (iHaveReviewed == true){
|
|
|
|
// We can skip messages that the user has already reviewed
|
|
//TODO: Create a mode where this behavior can be disabled
|
|
// Some moderators may want to keep those messages so they can reference them again, until they
|
|
// expire from the network, or they have been sufficiently banned
|
|
|
|
return false, nil
|
|
}
|
|
|
|
return true, nil
|
|
}
|
|
|
|
emptyList := make([][10]byte, 0)
|
|
|
|
err = queryHosts.DownloadMessagesFromHosts(true, networkType, myInboxRangeStart, myInboxRangeEnd, emptyList, false, true, checkIfMessageShouldBeDownloaded, 5)
|
|
if (err != nil) { return err }
|
|
|
|
return nil
|
|
}
|
|
|
|
|
|
// This function will download all reviews banning moderator identities.
|
|
// This is necessary if Moderator/Host mode is enabled.
|
|
// These reviews determine which moderators are banned, so they are needed to determine the moderation verdict for all identities/content.
|
|
// Thus, they must be downloaded by all hosts and moderators.
|
|
func DownloadModeratorIdentityBanningReviews(networkType byte)error{
|
|
|
|
isValid := helpers.VerifyNetworkType(networkType)
|
|
if (isValid == false){
|
|
networkTypeString := helpers.ConvertByteToString(networkType)
|
|
return errors.New("DownloadModeratorIdentityBanningReviews called with invalid networkType: " + networkTypeString)
|
|
}
|
|
|
|
minimumRange, maximumRange := byteRange.GetMinimumMaximumIdentityHashBounds()
|
|
|
|
emptyListA := make([][16]byte, 0)
|
|
emptyListB := make([][16]byte, 0)
|
|
|
|
checkIfReviewShouldBeDownloadedFunction := func(_ [29]byte, reviewedHash []byte)(bool, error){
|
|
|
|
reviewedType, err := helpers.GetReviewedTypeFromReviewedHash(reviewedHash)
|
|
if (err != nil) { return false, err }
|
|
if (reviewedType != "Identity" && reviewedType != "Profile" && reviewedType != "Attribute"){
|
|
return false, errors.New("DownloadIdentityReviewsFromHosts not checking that identity reviewed hash is valid.")
|
|
}
|
|
if (reviewedType == "Identity"){
|
|
return true, nil
|
|
}
|
|
|
|
return false, nil
|
|
}
|
|
|
|
err := queryHosts.DownloadIdentityReviewsFromHosts(false, networkType, "Moderator", minimumRange, maximumRange, emptyListA, emptyListB, checkIfReviewShouldBeDownloadedFunction, 5)
|
|
if (err != nil) { return err }
|
|
|
|
return nil
|
|
}
|
|
|
|
|
|
// This function will download reviews for identities/profiles/attributes within our Host range
|
|
// It is called periodically if Host mode is enabled.
|
|
func DownloadIdentityReviewsToHost(identityTypeToRetrieve string, networkType byte)error{
|
|
|
|
if (identityTypeToRetrieve != "Mate" && identityTypeToRetrieve != "Host" && identityTypeToRetrieve != "Moderator"){
|
|
return errors.New("DownloadIdentityReviewsToHost called with invalid identityTypeToRetrieve: " + identityTypeToRetrieve)
|
|
}
|
|
|
|
isValid := helpers.VerifyNetworkType(networkType)
|
|
if (isValid == false){
|
|
networkTypeString := helpers.ConvertByteToString(networkType)
|
|
return errors.New("DownloadIdentityReviewsToHost called with invalid networkType: " + networkTypeString)
|
|
}
|
|
|
|
hostModeEnabled, hostingAnyIdentities, myIdentityRangeStart, myIdentityRangeEnd, err := myRanges.GetMyIdentitiesToHostRange(identityTypeToRetrieve)
|
|
if (err != nil) { return err }
|
|
if (hostModeEnabled == false){
|
|
// Host mode is disabled. Nothing to do.
|
|
// This should not happen unless host mode was turned off recently
|
|
err := logger.AddLogEntry("Network", "DownloadIdentityReviewsToHost called when Host mode is disabled.")
|
|
if (err != nil) { return err }
|
|
|
|
return nil
|
|
}
|
|
if (hostingAnyIdentities == false){
|
|
|
|
// We are not hosting any identity reviews of the provided identityType
|
|
|
|
return nil
|
|
}
|
|
|
|
emptyListA := make([][16]byte, 0)
|
|
emptyListB := make([][16]byte, 0)
|
|
|
|
checkIfReviewShouldBeDownloadedFunction := func(_ [29]byte, _ []byte)(bool, error){
|
|
|
|
//TODO:
|
|
// We want to defend against downloading reviews that we will delete immediately.
|
|
// Don't download reviews by moderators who have been banned for a long enough period of time
|
|
// Don't download reviews for content/identities that have been expired for long enough
|
|
// Any hosts who offers us content that should no longer exist on the network would be a malicious host.
|
|
|
|
return true, nil
|
|
}
|
|
|
|
err = queryHosts.DownloadIdentityReviewsFromHosts(false, networkType, identityTypeToRetrieve, myIdentityRangeStart, myIdentityRangeEnd, emptyListA, emptyListB, checkIfReviewShouldBeDownloadedFunction, 5)
|
|
if (err != nil) { return err }
|
|
|
|
return nil
|
|
}
|
|
|
|
|
|
// This function will download reviews for messages within our Host range
|
|
// It is called periodically if Host mode is enabled.
|
|
func DownloadMessageReviewsToHost(networkType byte)error{
|
|
|
|
isValid := helpers.VerifyNetworkType(networkType)
|
|
if (isValid == false){
|
|
networkTypeString := helpers.ConvertByteToString(networkType)
|
|
return errors.New("DownloadMessageReviewsToHost called with invalid networkType: " + networkTypeString)
|
|
}
|
|
|
|
hostModeEnabled, hostingAnyInboxes, myInboxRangeStart, myInboxRangeEnd, err := myRanges.GetMyInboxesToHostRange()
|
|
if (err != nil) { return err }
|
|
if (hostModeEnabled == false){
|
|
// Host mode is disabled. Nothing to do.
|
|
// This should not happen unless host mode was turned off recently
|
|
err := logger.AddLogEntry("Network", "DownloadMessageReviewsToHost called when Host mode is disabled.")
|
|
if (err != nil) { return err }
|
|
|
|
return nil
|
|
}
|
|
if (hostingAnyInboxes == false){
|
|
|
|
// We are not hosting any message reviews
|
|
|
|
return nil
|
|
}
|
|
|
|
emptyListA := make([][26]byte, 0)
|
|
emptyListB := make([][16]byte, 0)
|
|
emptyMap := make(map[[26]byte][10]byte)
|
|
|
|
checkIfReviewShouldBeDownloadedFunction := func(reviewHash [29]byte, messageHash [26]byte)(bool, error){
|
|
|
|
//TODO:
|
|
// We want to defend against downloading reviews that we will delete immediately.
|
|
// Don't download reviews by moderators who have been banned for a long enough period of time
|
|
// Don't download reviews for messages that have been expired for long enough
|
|
// Any hosts who offers us content that should no longer exist on the network would be a malicious host.
|
|
|
|
return true, nil
|
|
}
|
|
|
|
err = queryHosts.DownloadMessageReviewsFromHosts(false, networkType, myInboxRangeStart, myInboxRangeEnd, emptyListA, emptyListB, emptyMap, checkIfReviewShouldBeDownloadedFunction, 5)
|
|
if (err != nil) { return err }
|
|
|
|
return nil
|
|
}
|
|
|
|
|
|
// This function will download reviews for identities/profiles/attributes within our moderation range
|
|
// This will be called periodically if Moderator mode is enabled.
|
|
func DownloadIdentityReviewsForModeration(identityTypeToRetrieve string, networkType byte)error{
|
|
|
|
if (identityTypeToRetrieve != "Mate" && identityTypeToRetrieve != "Host" && identityTypeToRetrieve != "Moderator"){
|
|
return errors.New("DownloadIdentityReviewsForModeration called with invalid identityTypeToRetrieve: " + identityTypeToRetrieve)
|
|
}
|
|
|
|
isValid := helpers.VerifyNetworkType(networkType)
|
|
if (isValid == false){
|
|
networkTypeString := helpers.ConvertByteToString(networkType)
|
|
return errors.New("DownloadIdentityReviewsForModeration called with invalid networkType: " + networkTypeString)
|
|
}
|
|
|
|
moderatorModeEnabled, moderatingAnyIdentities, myIdentityRangeStart, myIdentityRangeEnd, err := myRanges.GetMyIdentitiesToModerateRange(identityTypeToRetrieve)
|
|
if (err != nil) { return err }
|
|
if (moderatorModeEnabled == false){
|
|
// Moderator mode must have been disabled recently
|
|
|
|
err := logger.AddLogEntry("Network", "DownloadIdentityReviewsForModeration called when user is not in Moderator mode.")
|
|
if (err != nil) { return err }
|
|
|
|
return nil
|
|
}
|
|
if (moderatingAnyIdentities == false){
|
|
// We are not moderating any identities of the provided identityType
|
|
// We don't need to download any reviews for the identities
|
|
return nil
|
|
}
|
|
|
|
emptyListA := make([][16]byte, 0)
|
|
emptyListB := make([][16]byte, 0)
|
|
|
|
checkIfReviewShouldBeDownloadedFunction := func(reviewHash [29]byte, reviewedHash []byte)(bool, error){
|
|
|
|
//TODO
|
|
// see DownloadIdentityReviewsToHost for some ideas on what restrictions to add
|
|
|
|
return true, nil
|
|
}
|
|
|
|
err = queryHosts.DownloadIdentityReviewsFromHosts(false, networkType, identityTypeToRetrieve, myIdentityRangeStart, myIdentityRangeEnd, emptyListA, emptyListB, checkIfReviewShouldBeDownloadedFunction, 5)
|
|
if (err != nil) { return err }
|
|
|
|
return nil
|
|
}
|
|
|
|
|
|
// This function will download reviews for messages within our moderation range
|
|
// This will be called periodically if Moderator mode is enabled.
|
|
func DownloadMessageReviewsForModeration(networkType byte)error{
|
|
|
|
isValid := helpers.VerifyNetworkType(networkType)
|
|
if (isValid == false){
|
|
networkTypeString := helpers.ConvertByteToString(networkType)
|
|
return errors.New("DownloadMessageReviewsForModeration called with invalid networkType: " + networkTypeString)
|
|
}
|
|
|
|
moderatorModeEnabled, moderatingAnyInboxes, myInboxRangeStart, myInboxRangeEnd, err := myRanges.GetMyInboxesToModerateRange()
|
|
if (err != nil) { return err }
|
|
if (moderatorModeEnabled == false){
|
|
// Moderator mode must have been disabled recently
|
|
|
|
err := logger.AddLogEntry("Network", "DownloadMessageReviewsForModeration called when user is not in Moderator mode.")
|
|
if (err != nil) { return err }
|
|
|
|
return nil
|
|
}
|
|
if (moderatingAnyInboxes == false){
|
|
// We are not moderating any message inboxes
|
|
// We don't need to download any message reviews
|
|
return nil
|
|
}
|
|
|
|
emptyListA := make([][26]byte, 0)
|
|
emptyListB := make([][16]byte, 0)
|
|
emptyMap := make(map[[26]byte][10]byte)
|
|
|
|
checkIfReviewShouldBeDownloadedFunction := func(reviewHash [29]byte, reviewedMessageHash [26]byte)(bool, error){
|
|
|
|
//TODO
|
|
// see DownloadMessageReviewsToHost for some ideas on what restrictions to add
|
|
|
|
return true, nil
|
|
}
|
|
|
|
err = queryHosts.DownloadMessageReviewsFromHosts(false, networkType, myInboxRangeStart, myInboxRangeEnd, emptyListA, emptyListB, emptyMap, checkIfReviewShouldBeDownloadedFunction, 5)
|
|
if (err != nil) { return err }
|
|
|
|
return nil
|
|
}
|
|
|
|
|
|
// This function will download reports for identities/profiles/attributes within our host range
|
|
// It must be called if Host mode is enabled
|
|
func DownloadIdentityReportsToHost(identityTypeToRetrieve string, networkType byte)error{
|
|
|
|
if (identityTypeToRetrieve != "Mate" && identityTypeToRetrieve != "Host" && identityTypeToRetrieve != "Moderator"){
|
|
|
|
return errors.New("DownloadIdentityReportsToHost called with invalid identityTypeToRetrieve: " + identityTypeToRetrieve)
|
|
}
|
|
|
|
isValid := helpers.VerifyNetworkType(networkType)
|
|
if (isValid == false){
|
|
networkTypeString := helpers.ConvertByteToString(networkType)
|
|
return errors.New("DownloadIdentityReportsToHost called with invalid networkType: " + networkTypeString)
|
|
}
|
|
|
|
hostModeEnabled, hostingAnyIdentities, myIdentityRangeStart, myIdentityRangeEnd, err := myRanges.GetMyIdentitiesToHostRange(identityTypeToRetrieve)
|
|
if (err != nil) { return err }
|
|
if (hostModeEnabled == false){
|
|
// Host mode is disabled. Nothing to do.
|
|
// This should not happen unless host mode was turned off recently
|
|
err := logger.AddLogEntry("Network", "DownloadIdentityReportsToHost called when Host mode is disabled.")
|
|
if (err != nil) { return err }
|
|
|
|
return nil
|
|
}
|
|
if (hostingAnyIdentities == false){
|
|
return nil
|
|
}
|
|
|
|
checkIfReportShouldBeDownloaded := func(reportHash [30]byte, reportedHash []byte)(bool, error){
|
|
|
|
//TODO
|
|
// see DownloadReviewsToHost for some ideas on what restrictions to add
|
|
|
|
return true, nil
|
|
}
|
|
|
|
emptyList := make([][16]byte, 0)
|
|
|
|
err = queryHosts.DownloadIdentityReportsFromHosts(true, networkType, identityTypeToRetrieve, myIdentityRangeStart, myIdentityRangeEnd, emptyList, checkIfReportShouldBeDownloaded, 5)
|
|
if (err != nil) { return err }
|
|
|
|
return nil
|
|
}
|
|
|
|
|
|
// This function will download reports for messages within our host range
|
|
// It must be called if Host mode is enabled
|
|
func DownloadMessageReportsToHost(networkType byte)error{
|
|
|
|
isValid := helpers.VerifyNetworkType(networkType)
|
|
if (isValid == false){
|
|
networkTypeString := helpers.ConvertByteToString(networkType)
|
|
return errors.New("DownloadMessageReportsToHost called with invalid networkType: " + networkTypeString)
|
|
}
|
|
|
|
hostModeEnabled, hostingAnyInboxes, myInboxRangeStart, myInboxRangeEnd, err := myRanges.GetMyInboxesToHostRange()
|
|
if (err != nil) { return err }
|
|
if (hostModeEnabled == false){
|
|
// Host mode is disabled. Nothing to do.
|
|
// This should not happen unless host mode was turned off recently
|
|
err := logger.AddLogEntry("Network", "DownloadMessageReportsToHost called when Host mode is disabled.")
|
|
if (err != nil) { return err }
|
|
|
|
return nil
|
|
}
|
|
if (hostingAnyInboxes == false){
|
|
return nil
|
|
}
|
|
|
|
checkIfReportShouldBeDownloaded := func(reportHash [30]byte, reportedMessageHash [26]byte)(bool, error){
|
|
|
|
//TODO
|
|
// see DownloadMessageReportsToHost for some ideas on what restrictions to add
|
|
|
|
return true, nil
|
|
}
|
|
|
|
emptyList := make([][26]byte, 0)
|
|
emptyMap := make(map[[26]byte][10]byte)
|
|
|
|
err = queryHosts.DownloadMessageReportsFromHosts(true, networkType, myInboxRangeStart, myInboxRangeEnd, emptyList, emptyMap, checkIfReportShouldBeDownloaded, 5)
|
|
if (err != nil) { return err }
|
|
|
|
return nil
|
|
}
|
|
|
|
// This function will download reports for identities/profiles/attributes within our moderation range
|
|
// It is called periodically if Moderator mode is enabled
|
|
func DownloadIdentityReportsForModeration(identityTypeToRetrieve string, networkType byte)error{
|
|
|
|
if (identityTypeToRetrieve != "Mate" && identityTypeToRetrieve != "Host" && identityTypeToRetrieve != "Moderator"){
|
|
|
|
return errors.New("DownloadIdentityReportsForModeration called with invalid identityTypeToRetrieve: " + identityTypeToRetrieve)
|
|
}
|
|
|
|
isValid := helpers.VerifyNetworkType(networkType)
|
|
if (isValid == false){
|
|
networkTypeString := helpers.ConvertByteToString(networkType)
|
|
return errors.New("DownloadIdentityReportsForModeration called with invalid networkType: " + networkTypeString)
|
|
}
|
|
|
|
moderatorModeEnabled, moderatingAny, myRangeStart, myRangeEnd, err := myRanges.GetMyIdentitiesToModerateRange(identityTypeToRetrieve)
|
|
if (err != nil) { return err }
|
|
if (moderatorModeEnabled == false){
|
|
|
|
// Moderator mode must have been disabled recently
|
|
|
|
err := logger.AddLogEntry("Network", "DownloadIdentityReportsForModeration called when user is not in Moderator mode.")
|
|
if (err != nil) { return err }
|
|
|
|
return nil
|
|
}
|
|
if (moderatingAny == false){
|
|
|
|
// Not moderating any identities of provided identityType
|
|
// We don't need to download reports
|
|
return nil
|
|
}
|
|
|
|
checkIfReportShouldBeDownloaded := func(reportHash [30]byte, reportedHash []byte)(bool, error){
|
|
|
|
//TODO
|
|
// see DownloadIdentityReviewsToHost for some ideas on what restrictions to add
|
|
|
|
return true, nil
|
|
}
|
|
|
|
emptyList := make([][16]byte, 0)
|
|
|
|
err = queryHosts.DownloadIdentityReportsFromHosts(true, networkType, identityTypeToRetrieve, myRangeStart, myRangeEnd, emptyList, checkIfReportShouldBeDownloaded, 5)
|
|
if (err != nil) { return err }
|
|
|
|
return nil
|
|
}
|
|
|
|
|
|
// This function will download reports for messages/profiles/identities within our moderation range
|
|
// It is called periodically if Moderator mode is enabled
|
|
func DownloadMessageReportsForModeration(networkType byte)error{
|
|
|
|
isValid := helpers.VerifyNetworkType(networkType)
|
|
if (isValid == false){
|
|
networkTypeString := helpers.ConvertByteToString(networkType)
|
|
return errors.New("DownloadMessageReportsForModeration called with invalid networkType: " + networkTypeString)
|
|
}
|
|
|
|
moderatorModeEnabled, moderatingAny, myInboxRangeStart, myInboxRangeEnd, err := myRanges.GetMyInboxesToModerateRange()
|
|
if (err != nil) { return err }
|
|
if (moderatorModeEnabled == false){
|
|
|
|
// Moderator mode must have been disabled recently
|
|
|
|
err := logger.AddLogEntry("Network", "DownloadMessageReportsForModeration called when user is not in Moderator mode.")
|
|
if (err != nil) { return err }
|
|
|
|
return nil
|
|
}
|
|
if (moderatingAny == false){
|
|
// Not moderating any messages
|
|
// We don't need to download any message reports
|
|
return nil
|
|
}
|
|
|
|
checkIfReportShouldBeDownloaded := func(reportHash [30]byte, reportedMessageHash [26]byte)(bool, error){
|
|
|
|
//TODO
|
|
// see DownloadMessageReviewsToHost for some ideas on what restrictions to add
|
|
|
|
return true, nil
|
|
}
|
|
|
|
emptyList := make([][26]byte, 0)
|
|
emptyMap := make(map[[26]byte][10]byte)
|
|
|
|
err = queryHosts.DownloadMessageReportsFromHosts(true, networkType, myInboxRangeStart, myInboxRangeEnd, emptyList, emptyMap, checkIfReportShouldBeDownloaded, 5)
|
|
if (err != nil) { return err }
|
|
|
|
return nil
|
|
}
|
|
|
|
|
|
// This function will download trusted viewable statuses for downloaded host identities/profiles.
|
|
// Downloading these statuses is not needed if a user is able to determine these statuses themselves
|
|
//
|
|
// Hosts who are hosting host identities will download all host profile reviews, so they can calculate the viewable status themselves
|
|
// Moderators who are moderating Host identities can also calculate the viewable status for host identities/profiles within their moderation range
|
|
func DownloadHostViewableStatuses(networkType byte, knownOrUnknown string)error{
|
|
|
|
isValid := helpers.VerifyNetworkType(networkType)
|
|
if (isValid == false){
|
|
networkTypeString := helpers.ConvertByteToString(networkType)
|
|
return errors.New("DownloadHostViewableStatuses called with invalid networkType: " + networkTypeString)
|
|
}
|
|
|
|
if (knownOrUnknown != "Known" && knownOrUnknown != "Unknown"){
|
|
return errors.New("DownloadHostViewableStatuses called with invalid knownOrUnknown: " + knownOrUnknown)
|
|
}
|
|
|
|
hostModeEnabled, hostingAny, _, _, err := myRanges.GetMyIdentitiesToHostRange("Host")
|
|
if (err != nil) { return err }
|
|
if (hostModeEnabled == true && hostingAny == true){
|
|
// We are already hosting all reviews for host identities, so we can calculate the viewable status of host profiles ourselves
|
|
// Thus, we don't need to download any trusted viewable statuses for host identitites/profiles
|
|
return nil
|
|
}
|
|
|
|
allHostProfileIdentityHashesList, err := badgerDatabase.GetAllProfileIdentityHashes("Host")
|
|
if (err != nil) { return err }
|
|
|
|
getRelevantHostProfileIdentityHashesList := func()([][16]byte, error){
|
|
|
|
moderatorModeEnabled, moderatingAny, identityRangeStart, identityRangeEnd, err := myRanges.GetMyIdentitiesToModerateRange("Host")
|
|
if (err != nil) { return nil, err }
|
|
if (moderatorModeEnabled == false || moderatingAny == false){
|
|
// We are not moderating any host identities
|
|
// We do not need to reduce the list at all
|
|
return allHostProfileIdentityHashesList, nil
|
|
}
|
|
|
|
relevantHostProfileIdentityHashesList := make([][16]byte, 0)
|
|
|
|
for _, hostIdentityHash := range allHostProfileIdentityHashesList{
|
|
|
|
isWithinMyRange, err := byteRange.CheckIfIdentityHashIsWithinRange(identityRangeStart, identityRangeEnd, hostIdentityHash)
|
|
if (err != nil) { return nil, err }
|
|
if (isWithinMyRange == true){
|
|
// We don't need to download this host's viewable status, because we can calculate it ourselves.
|
|
continue
|
|
}
|
|
|
|
relevantHostProfileIdentityHashesList = append(relevantHostProfileIdentityHashesList, hostIdentityHash)
|
|
}
|
|
|
|
return relevantHostProfileIdentityHashesList, nil
|
|
}
|
|
|
|
relevantHostProfileIdentityHashesList, err := getRelevantHostProfileIdentityHashesList()
|
|
if (err != nil) { return err }
|
|
|
|
// Map Structure: Profile Hash -> Author identity hash
|
|
profileHashesToRetrieveMap := make(map[[28]byte][16]byte)
|
|
|
|
for _, identityHash := range relevantHostProfileIdentityHashesList{
|
|
|
|
exists, profileHashesList, err := badgerDatabase.GetIdentityProfileHashesList(identityHash)
|
|
if (err != nil) { return err }
|
|
if (exists == false){
|
|
// Entry must have been deleted. Will be fixed automatically
|
|
continue
|
|
}
|
|
if (len(profileHashesList) == 0){
|
|
continue
|
|
}
|
|
|
|
for _, profileHash := range profileHashesList{
|
|
|
|
profileMetadataExists, _, profileNetworkType, profileAuthor, _, profileIsDisabled, _, _, err := contentMetadata.GetProfileMetadata(profileHash)
|
|
if (err != nil) { return err }
|
|
if (profileMetadataExists == false){
|
|
// Profile is not downloaded, skip it.
|
|
continue
|
|
}
|
|
if (profileNetworkType != networkType){
|
|
continue
|
|
}
|
|
if (profileAuthor != identityHash){
|
|
return errors.New("Database corrupt: Host identity profile hashes list contains profile of different identity")
|
|
}
|
|
|
|
if (profileIsDisabled == true){
|
|
continue
|
|
}
|
|
|
|
profileHashesToRetrieveMap[profileHash] = identityHash
|
|
}
|
|
}
|
|
|
|
err = queryHosts.DownloadViewableStatusesFromHosts(false, networkType, knownOrUnknown, relevantHostProfileIdentityHashesList, profileHashesToRetrieveMap, 5)
|
|
if (err != nil) { return err }
|
|
|
|
return nil
|
|
}
|
|
|
|
// This function will download trusted viewable statuses for downloaded moderator profiles whose viewable statuses we cannot calculate ourselves
|
|
//
|
|
// We only need to do this is Moderator mode is enabled.
|
|
// This is only needed so moderators can view Moderator profiles whose viewable status we are not aware of and be sure they are viewable
|
|
// If Host mode is enabled, all of the moderator profiles we download, we will be able to determine the viewable status of.
|
|
// Mate mode will not download any moderator profiles.
|
|
//
|
|
// We don't need to download viewable statuses for moderator identities
|
|
// This is because in Moderator/Host mode, we should be downloading all moderator identity reviews
|
|
// Thus, we should be able to determine their viewable statuses ourselves
|
|
//
|
|
func DownloadModeratorProfileViewableStatuses(networkType byte, knownOrUnknown string)error{
|
|
|
|
isValid := helpers.VerifyNetworkType(networkType)
|
|
if (isValid == false){
|
|
networkTypeString := helpers.ConvertByteToString(networkType)
|
|
return errors.New("DownloadModeratorProfileViewableStatuses called with invalid networkType: " + networkTypeString)
|
|
}
|
|
|
|
if (knownOrUnknown != "Known" && knownOrUnknown != "Unknown"){
|
|
return errors.New("DownloadModeratorProfileViewableStatuses called with invalid knownOrUnknown: " + knownOrUnknown)
|
|
}
|
|
|
|
moderatorModeEnabled, moderatingAnyModeratorIdentities, myIdentityRangeStart, myIdentityRangeEnd, err := myRanges.GetMyIdentitiesToModerateRange("Moderator")
|
|
if (err != nil) { return err }
|
|
if (moderatorModeEnabled == false){
|
|
// Moderator mode must have been disabled recently
|
|
|
|
err := logger.AddLogEntry("Network", "DownloadModeratorProfileViewableStatuses called when user is not in Moderator mode.")
|
|
if (err != nil) { return err }
|
|
|
|
return nil
|
|
}
|
|
|
|
if (moderatingAnyModeratorIdentities == true){
|
|
|
|
minimumIdentityBound, maximumIdentityBound := byteRange.GetMinimumMaximumIdentityHashBounds()
|
|
|
|
if (myIdentityRangeStart == minimumIdentityBound && myIdentityRangeEnd == maximumIdentityBound){
|
|
|
|
// We are moderating all Moderator identities, so we should be able to determine the viewable status for all moderator profiles
|
|
// We don't need to download any moderator profile trusted viewable statuses
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// Now we see if we are hosting all moderator identities
|
|
|
|
hostModeEnabled, hostingAny, _, _, err := myRanges.GetMyIdentitiesToHostRange("Moderator")
|
|
if (err != nil) { return err }
|
|
if (hostModeEnabled == true && hostingAny == true){
|
|
// We are hosting all moderator identities
|
|
// Thus, we are downloading all reviews for all moderator profiles
|
|
// We don't need to download the viewable statuses for any moderator profiles
|
|
return nil
|
|
}
|
|
|
|
allModeratorProfileIdentityHashesList, err := badgerDatabase.GetAllProfileIdentityHashes("Moderator")
|
|
if (err != nil) { return err }
|
|
|
|
// Map Structure: Profile Hash -> Author identity hash
|
|
profileHashesToRetrieveMap := make(map[[28]byte][16]byte)
|
|
|
|
for _, moderatorIdentityHash := range allModeratorProfileIdentityHashesList{
|
|
|
|
if (moderatingAnyModeratorIdentities == true){
|
|
|
|
// We see if moderator's identity is within our range
|
|
// If it is, we don't have to get the status for profiles authored by this identity, because we can determine the viewable statuses ourselves
|
|
|
|
isWithinRange, err := byteRange.CheckIfIdentityHashIsWithinRange(myIdentityRangeStart, myIdentityRangeEnd, moderatorIdentityHash)
|
|
if (err != nil) { return err }
|
|
if (isWithinRange == true){
|
|
|
|
continue
|
|
}
|
|
}
|
|
|
|
exists, profileHashesList, err := badgerDatabase.GetIdentityProfileHashesList(moderatorIdentityHash)
|
|
if (err != nil) { return err }
|
|
if (exists == false){
|
|
// Entry must have been deleted. Will be fixed automatically
|
|
continue
|
|
}
|
|
if (len(profileHashesList) == 0){
|
|
continue
|
|
}
|
|
|
|
for _, profileHash := range profileHashesList{
|
|
|
|
profileMetadataExists, _, profileNetworkType, profileAuthor, _, profileIsDisabled, _, _, err := contentMetadata.GetProfileMetadata(profileHash)
|
|
if (err != nil) { return err }
|
|
if (profileMetadataExists == false){
|
|
// Profile is not downloaded, skip it.
|
|
continue
|
|
}
|
|
if (profileNetworkType != networkType){
|
|
continue
|
|
}
|
|
if (profileAuthor != moderatorIdentityHash){
|
|
return errors.New("Database corrupt: Moderator identity profile hashes list contains profile of different identity")
|
|
}
|
|
|
|
if (profileIsDisabled == true){
|
|
continue
|
|
}
|
|
|
|
profileHashesToRetrieveMap[profileHash] = moderatorIdentityHash
|
|
}
|
|
}
|
|
|
|
emptyList := make([][16]byte, 0)
|
|
|
|
err = queryHosts.DownloadViewableStatusesFromHosts(false, networkType, knownOrUnknown, emptyList, profileHashesToRetrieveMap, 5)
|
|
if (err != nil) { return err }
|
|
|
|
return nil
|
|
}
|
|
|
|
// This function will download viewable statuses for mate identities/profiles we are browsing
|
|
// If we are not in DesiresPruningMode, we will download the statuses for all downloaded profiles/identities which fulfill our criteria
|
|
// If we are in DesiresPruningMode, we have to download the statuses for our matches profiles/identities one-at-a-time
|
|
func DownloadMateViewableStatusesForBrowsing(networkType byte, knownOrUnknown string)error{
|
|
|
|
isValid := helpers.VerifyNetworkType(networkType)
|
|
if (isValid == false){
|
|
networkTypeString := helpers.ConvertByteToString(networkType)
|
|
return errors.New("DownloadMateViewableStatusesForBrowsing called with invalid networkType: " + networkTypeString)
|
|
}
|
|
|
|
if (knownOrUnknown != "Known" && knownOrUnknown != "Unknown"){
|
|
return errors.New("DownloadMateViewableStatusesForBrowsing called with invalid knownOrUnknown: " + knownOrUnknown)
|
|
}
|
|
|
|
//TODO: Fix
|
|
desiresPruningMode := false
|
|
|
|
if (desiresPruningMode == true){
|
|
|
|
// We will retrieve consensus statuses for all users who could potentially be matches one-by-one
|
|
// A user could potentially be a match if their newest profile fulfills our desires
|
|
// Their newest profile may not be viewable, so we still need to retrieve statuses for all of their profiles which fulfill our desires
|
|
|
|
myIdentityExists, myIdentityHash, err := myIdentity.GetMyIdentityHash("Mate")
|
|
if (err != nil) { return err }
|
|
|
|
mateIdentityHashesList, err := badgerDatabase.GetAllProfileIdentityHashes("Mate")
|
|
if (err != nil) { return err }
|
|
|
|
for _, userIdentityHash := range mateIdentityHashesList{
|
|
|
|
if (myIdentityExists == true && userIdentityHash == myIdentityHash){
|
|
continue
|
|
}
|
|
|
|
userIsBlocked, _, _, _, err := myBlockedUsers.CheckIfUserIsBlocked(userIdentityHash)
|
|
if (err != nil) { return err }
|
|
if (userIsBlocked == true){
|
|
// We don't need to get the viewable statuses for blocked users
|
|
continue
|
|
}
|
|
|
|
profileExists, profileVersion, newestProfileHash, _, _, newestRawProfileMap, err := profileStorage.GetNewestUserProfile(userIdentityHash, networkType)
|
|
if (err != nil) { return err }
|
|
if (profileExists == false){
|
|
// This user has no profiles, so we do not need to retrieve any viewable statuses for this user
|
|
// The user's profile was probably deleted in the background
|
|
continue
|
|
}
|
|
|
|
userIsDisabled, _, err := readProfiles.GetFormattedProfileAttributeFromRawProfileMap(newestRawProfileMap, "Disabled")
|
|
if (err != nil) { return err }
|
|
if (userIsDisabled == true){
|
|
// The user will never be a match, because their newest profile is disabled
|
|
// Thus, we do not need to retrieve viewable statuses for the user.
|
|
continue
|
|
}
|
|
|
|
getAnyProfileAttributeFunction, err := calculatedAttributes.GetRetrieveAnyProfileAttributeIncludingCalculatedFunction(profileVersion, newestRawProfileMap)
|
|
if (err != nil){ return err }
|
|
|
|
profilePassesMyDesires, err := myMateDesires.CheckIfMateProfilePassesAllMyDesires(false, "", getAnyProfileAttributeFunction)
|
|
if (err != nil) { return err }
|
|
if (profilePassesMyDesires == false){
|
|
// The user's newest profile does not fulfill our desires
|
|
// We don't need to get this profile's viewable status, because it does not fulfill our desires
|
|
// We don't need to get any viewable statuses for this user, unless they are an outlier
|
|
continue
|
|
}
|
|
|
|
anyExist, profileHashesList, err := badgerDatabase.GetIdentityProfileHashesList(userIdentityHash)
|
|
if (err != nil) { return err }
|
|
if (anyExist == false){
|
|
// This user has no profiles
|
|
continue
|
|
}
|
|
|
|
profileHashesToGetStatusesOfList := [][28]byte{newestProfileHash}
|
|
|
|
for _, profileHash := range profileHashesList{
|
|
|
|
if (profileHash == newestProfileHash){
|
|
// We are already getting this profile's status
|
|
continue
|
|
}
|
|
|
|
profileExists, profileBytes, err := badgerDatabase.GetUserProfile("Mate", profileHash)
|
|
if (err != nil) { return err }
|
|
if (profileExists == false){
|
|
continue
|
|
}
|
|
|
|
ableToRead, profileVersion, profileNetworkType, profileAuthor, _, profileIsDisabled, rawProfileMap, err := readProfiles.ReadProfile(false, profileBytes)
|
|
if (err != nil) { return err }
|
|
if (ableToRead == false){
|
|
return errors.New("Database corrupt: Contains malformed profile.")
|
|
}
|
|
if (profileNetworkType != networkType){
|
|
// Profile belongs to a different network type.
|
|
continue
|
|
}
|
|
if (profileAuthor != userIdentityHash){
|
|
return errors.New("Database corrupt: Mate identity profile hashes list contains profile of different identity")
|
|
}
|
|
if (profileIsDisabled == true){
|
|
// We don't need to retrieve status for disabled profiles.
|
|
// These profiles will always be viewable, unless their author is banned.
|
|
continue
|
|
}
|
|
|
|
getAnyProfileAttributeFunction, err := calculatedAttributes.GetRetrieveAnyProfileAttributeIncludingCalculatedFunction(profileVersion, rawProfileMap)
|
|
if (err != nil){ return err }
|
|
|
|
profilePassesMyDesires, err := myMateDesires.CheckIfMateProfilePassesAllMyDesires(false, "", getAnyProfileAttributeFunction)
|
|
if (err != nil) { return err }
|
|
if (profilePassesMyDesires == false){
|
|
// We don't need to get this profile's viewable status, because it does not fulfill our desires
|
|
// Thus, we will not show it to the user unless the author is an outlier
|
|
// Outlier viewable statuses are retrieved in a different job
|
|
continue
|
|
}
|
|
|
|
profileHashesToGetStatusesOfList = append(profileHashesToGetStatusesOfList, profileHash)
|
|
}
|
|
|
|
// Map Structure: Profile Hash -> User Identity Hash
|
|
profileHashesToRetrieveMap := make(map[[28]byte][16]byte)
|
|
|
|
for _, profileHash := range profileHashesToGetStatusesOfList{
|
|
|
|
profileHashesToRetrieveMap[profileHash] = userIdentityHash
|
|
}
|
|
|
|
identityHashList := [][16]byte{userIdentityHash}
|
|
|
|
err = queryHosts.DownloadViewableStatusesFromHosts(false, networkType, knownOrUnknown, identityHashList, profileHashesToRetrieveMap, 1)
|
|
if (err != nil) { return err }
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// We will retrieve statuses for all identities whose newest profile fulfills our downloads criteria, and their profiles that fulfill our criteria
|
|
|
|
myCriteriaExists, myCriteria, err := myMateCriteria.GetMyMateDownloadsCriteria()
|
|
if (err != nil) { return err }
|
|
|
|
allMateProfileIdentityHashesList, err := badgerDatabase.GetAllProfileIdentityHashes("Mate")
|
|
if (err != nil) { return err }
|
|
|
|
helpers.RandomizeListOrder(allMateProfileIdentityHashesList)
|
|
|
|
identityHashesToRetrieveList := make([][16]byte, 0)
|
|
|
|
// Map Structure: Profile Hash -> User Identity Hash
|
|
profileHashesToRetrieveMap := make(map[[28]byte][16]byte)
|
|
|
|
for _, userIdentityHash := range allMateProfileIdentityHashesList{
|
|
|
|
statusIsKnown, identityIsFunded, err := fundedStatus.GetIdentityIsFundedStatus(userIdentityHash, networkType)
|
|
if (err != nil) { return err }
|
|
if (statusIsKnown == true && identityIsFunded == false){
|
|
|
|
// The user's identity is not funded
|
|
// This means that none of their profiles will be hosted by the network
|
|
// We won't try to retrieve their viewable status, because their profile/identity will not exist on the network
|
|
continue
|
|
}
|
|
|
|
profileExists, profileVersion, newestProfileHash, _, _, newestRawProfileMap, err := profileStorage.GetNewestUserProfile(userIdentityHash, networkType)
|
|
if (err != nil) { return err }
|
|
if (profileExists == false){
|
|
continue
|
|
}
|
|
|
|
userIsDisabled, _, err := readProfiles.GetFormattedProfileAttributeFromRawProfileMap(newestRawProfileMap, "Disabled")
|
|
if (err != nil) { return err }
|
|
if (userIsDisabled == true){
|
|
// The user will never be a match, because their newest profile is disabled
|
|
// Thus, we do not need to retrieve viewable statuses for the user.
|
|
continue
|
|
}
|
|
|
|
if (myCriteriaExists == true){
|
|
|
|
criteriaIsValid, fulfillsCriteria, err := mateCriteria.CheckIfMateProfileFulfillsCriteria(true, profileVersion, newestRawProfileMap, myCriteria)
|
|
if (err != nil) { return err }
|
|
if (criteriaIsValid == false){
|
|
return errors.New("GetMyMateDownloadsCriteria returning invalid criteria.")
|
|
}
|
|
|
|
if (fulfillsCriteria == false){
|
|
// This user's newest profile does not fulfill our criteria. Skip them.
|
|
// DatabaseJobs will delete all of their profiles (unless they are an outlier)
|
|
continue
|
|
}
|
|
}
|
|
|
|
anyExist, profileHashesList, err := badgerDatabase.GetIdentityProfileHashesList(userIdentityHash)
|
|
if (err != nil) { return err }
|
|
if (anyExist == false){
|
|
// User has no profiles
|
|
// They must have been deleted after earlier check
|
|
continue
|
|
}
|
|
|
|
for _, profileHash := range profileHashesList{
|
|
|
|
if (profileHash == newestProfileHash){
|
|
// We already checked and know that this profile fulfills our criteria
|
|
profileHashesToRetrieveMap[profileHash] = userIdentityHash
|
|
continue
|
|
}
|
|
|
|
profileExists, profileBytes, err := badgerDatabase.GetUserProfile("Mate", profileHash)
|
|
if (err != nil) { return err }
|
|
if (profileExists == false){
|
|
continue
|
|
}
|
|
|
|
ableToRead, profileVersion, profileNetworkType, profileAuthor, _, profileIsDisabled, rawProfileMap, err := readProfiles.ReadProfile(false, profileBytes)
|
|
if (err != nil) { return err }
|
|
if (ableToRead == false){
|
|
return errors.New("Database corrupt: Contains malformed profile.")
|
|
}
|
|
if (profileNetworkType != networkType){
|
|
// Profile belongs to a different network type.
|
|
continue
|
|
}
|
|
if (profileAuthor != userIdentityHash){
|
|
return errors.New("Database corrupt: Mate identity profile hashes list contains profile of different identity")
|
|
}
|
|
if (profileIsDisabled == true){
|
|
// We don't need to retrieve status for disabled profiles. They are always approved, unless identity is banned.
|
|
continue
|
|
}
|
|
|
|
if (myCriteriaExists == true){
|
|
|
|
criteriaIsValid, fulfillsCriteria, err := mateCriteria.CheckIfMateProfileFulfillsCriteria(true, profileVersion, rawProfileMap, myCriteria)
|
|
if (err != nil) { return err }
|
|
if (criteriaIsValid == false){
|
|
return errors.New("GetMyMateDownloadsCriteria returning invalid criteria.")
|
|
}
|
|
|
|
if (fulfillsCriteria == false){
|
|
// This profile does not fulfill our criteria
|
|
// We don't need to get its viewable status, because it will never be shown to the user
|
|
// The exception is if the profile is an outlier, in which case we will retrieve its status using DownloadMateOutlierViewableStatuses
|
|
// Another reason we skip the profile is that requesting its status would pose a risk of exposing our older criteria to the host
|
|
continue
|
|
}
|
|
}
|
|
|
|
profileHashesToRetrieveMap[profileHash] = userIdentityHash
|
|
}
|
|
|
|
identityHashesToRetrieveList = append(identityHashesToRetrieveList, userIdentityHash)
|
|
}
|
|
|
|
if (len(identityHashesToRetrieveList) == 0){
|
|
// No users fulfill our criteria. Nothing to do.
|
|
return nil
|
|
}
|
|
|
|
err = queryHosts.DownloadViewableStatusesFromHosts(false, networkType, knownOrUnknown, identityHashesToRetrieveList, profileHashesToRetrieveMap, 5)
|
|
if (err != nil) { return err }
|
|
|
|
return nil
|
|
}
|
|
|
|
// This function will download trusted viewable statuses for Mate users whom are our outliers
|
|
// Outliers are either contacts, likes, or chat recipients.
|
|
// We download them so the user's client will have their downloaded profiles viewable, even if the users do not fulfill our criteria
|
|
// These need to be downloaded one-by-one to prevent any host from learning our contacts/likes/chat recipients
|
|
func DownloadMateOutlierViewableStatuses(outlierType string, networkType byte, knownOrUnknown string)error{
|
|
|
|
if (outlierType != "Contacts" && outlierType != "Likes" && outlierType != "ChatRecipients"){
|
|
return errors.New("DownloadMateOutlierViewableStatuses called with invalid outlierType: " + outlierType)
|
|
}
|
|
isValid := helpers.VerifyNetworkType(networkType)
|
|
if (isValid == false){
|
|
networkTypeString := helpers.ConvertByteToString(networkType)
|
|
return errors.New("DownloadMateOutlierViewableStatuses called with invalid networkType: " + networkTypeString)
|
|
}
|
|
|
|
if (knownOrUnknown != "Known" && knownOrUnknown != "Unknown"){
|
|
return errors.New("DownloadMateOutlierViewableStatuses called with invalid knownOrUnknown: " + knownOrUnknown)
|
|
}
|
|
|
|
//Outputs:
|
|
// -[]string: List of identities
|
|
// -error
|
|
getMyOutlierIdentitiesList := func()([][16]byte, error){
|
|
|
|
if (outlierType == "Contacts"){
|
|
|
|
myContactIdentityHashesList, err := myContacts.GetMyContactsList("Mate")
|
|
if (err != nil) { return nil, err }
|
|
|
|
return myContactIdentityHashesList, nil
|
|
}
|
|
if (outlierType == "Likes"){
|
|
|
|
myLikedUsersList, err := myLikedUsers.GetMyLikedUsersList()
|
|
if (err != nil) { return nil, err }
|
|
|
|
return myLikedUsersList, nil
|
|
}
|
|
|
|
myIdentityExists, chatRecipientIdentityHashesList, err := myChatMessages.GetAllMyNonBlockedChatRecipients("Mate", networkType)
|
|
if (err != nil) { return nil, err }
|
|
if (myIdentityExists == false){
|
|
// Nothing to do, mate identity does not exist
|
|
emptyList := make([][16]byte, 0)
|
|
return emptyList, nil
|
|
}
|
|
|
|
return chatRecipientIdentityHashesList, nil
|
|
}
|
|
|
|
myOutlierIdentityHashesList, err := getMyOutlierIdentitiesList()
|
|
if (err != nil) { return err }
|
|
if (len(myOutlierIdentityHashesList) == 0){
|
|
return nil
|
|
}
|
|
|
|
helpers.RandomizeListOrder(myOutlierIdentityHashesList)
|
|
|
|
for _, mateIdentityHash := range myOutlierIdentityHashesList{
|
|
|
|
statusIsKnown, identityIsFunded, err := fundedStatus.GetIdentityIsFundedStatus(mateIdentityHash, networkType)
|
|
if (err != nil) { return err }
|
|
if (statusIsKnown == true && identityIsFunded == false){
|
|
|
|
// The user's identity is not funded
|
|
// This means that none of their profiles will be hosted by the network
|
|
// We won't try to retrieve their viewable status, because their profile/identity will not exist on the network
|
|
continue
|
|
}
|
|
|
|
identityHashList := [][16]byte{mateIdentityHash}
|
|
|
|
// Outputs:
|
|
// -map[[28]byte][16]byte: Map of profile hashes whose viewable status we want to retrieve (Profile Hash -> User identity Hash)
|
|
// -error
|
|
getProfileHashesToRetrieveMap := func()(map[[28]byte][16]byte, error){
|
|
|
|
profileExists, _, newestProfileHash, _, _, newestRawProfileMap, err := profileStorage.GetNewestUserProfile(mateIdentityHash, networkType)
|
|
if (err != nil) { return nil, err }
|
|
if (profileExists == false){
|
|
// We have no profiles downloaded for this user
|
|
emptyMap := make(map[[28]byte][16]byte)
|
|
|
|
return emptyMap, nil
|
|
}
|
|
|
|
isDisabled, _, err := readProfiles.GetFormattedProfileAttributeFromRawProfileMap(newestRawProfileMap, "Disabled")
|
|
if (err != nil) { return nil, err }
|
|
if (isDisabled == true){
|
|
|
|
// User's newest profile is disabled.
|
|
// We don't need to download the profile's viewable status, because it cannot be banned
|
|
|
|
emptyMap := make(map[[28]byte][16]byte)
|
|
|
|
return emptyMap, nil
|
|
}
|
|
|
|
// We retrieve the viewable status for all of their downloaded profiles
|
|
|
|
profileHashesToRetrieveMap := map[[28]byte][16]byte{
|
|
newestProfileHash: mateIdentityHash,
|
|
}
|
|
|
|
anyExist, identityProfileHashesList, err := badgerDatabase.GetIdentityProfileHashesList(mateIdentityHash)
|
|
if (err != nil) { return nil, err }
|
|
if (anyExist == true){
|
|
|
|
for _, profileHash := range identityProfileHashesList{
|
|
profileHashesToRetrieveMap[profileHash] = mateIdentityHash
|
|
}
|
|
}
|
|
|
|
return profileHashesToRetrieveMap, nil
|
|
}
|
|
|
|
profileHashesToRetrieveMap, err := getProfileHashesToRetrieveMap()
|
|
if (err != nil) { return err }
|
|
|
|
err = queryHosts.DownloadViewableStatusesFromHosts(false, networkType, knownOrUnknown, identityHashList, profileHashesToRetrieveMap, 1)
|
|
if (err != nil) { return err }
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// This function will download the cryptocurrency deposit history for all downloaded moderator identities
|
|
// We download deposits for all moderators in bulk
|
|
// Because users must download either all or no moderator profiles, there is no fingerprinting risk in downloading them in bulk
|
|
// This should be called if Host/Moderator mode is enabled
|
|
func DownloadModeratorIdentityDeposits(networkType byte, unknownOrKnown string)error{
|
|
|
|
isValid := helpers.VerifyNetworkType(networkType)
|
|
if (isValid == false){
|
|
networkTypeString := helpers.ConvertByteToString(networkType)
|
|
return errors.New("DownloadModeratorIdentityDeposits called with invalid networkType: " + networkTypeString)
|
|
}
|
|
|
|
err := queryHosts.DownloadModeratorAddressDepositsFromHosts(true, networkType, "Ethereum", unknownOrKnown, 6)
|
|
if (err != nil) { return err }
|
|
|
|
err = queryHosts.DownloadModeratorAddressDepositsFromHosts(true, networkType, "Cardano", unknownOrKnown, 6)
|
|
if (err != nil) { return err }
|
|
|
|
return nil
|
|
}
|
|
|
|
|