2934 lines
106 KiB
Go
2934 lines
106 KiB
Go
|
|
// craftResponses provides a function to craft server responses to peer requests
|
|
|
|
package craftResponses
|
|
|
|
//TODO: Restrict responses based on if host is in HostViewable..Only mode
|
|
//TODO: Add a response called Response Too Large, which means that the requestor has to
|
|
// reduce their requested range for the host's response to fit within the maximum allowed size
|
|
// We can check if a response has become too large as we craft each response
|
|
|
|
import "seekia/internal/badgerDatabase"
|
|
import "seekia/internal/byteRange"
|
|
import "seekia/internal/contentMetadata"
|
|
import "seekia/internal/encoding"
|
|
import "seekia/internal/helpers"
|
|
import "seekia/internal/identity"
|
|
import "seekia/internal/logger"
|
|
import "seekia/internal/messaging/chatMessageStorage"
|
|
import "seekia/internal/messaging/readMessages"
|
|
import "seekia/internal/moderation/moderatorScores"
|
|
import "seekia/internal/moderation/readReports"
|
|
import "seekia/internal/moderation/readReviews"
|
|
import "seekia/internal/moderation/reportStorage"
|
|
import "seekia/internal/moderation/reviewStorage"
|
|
import "seekia/internal/moderation/verifiedStickyStatus"
|
|
import "seekia/internal/myIdentity"
|
|
import "seekia/internal/myRanges"
|
|
import "seekia/internal/network/mateCriteria"
|
|
import "seekia/internal/network/serverRequest"
|
|
import "seekia/internal/network/serverResponse"
|
|
import "seekia/internal/network/verifiedFundedStatus"
|
|
import "seekia/internal/parameters/parametersStorage"
|
|
import "seekia/internal/parameters/readParameters"
|
|
import "seekia/internal/profiles/profileStorage"
|
|
import "seekia/internal/profiles/readProfiles"
|
|
import "seekia/internal/profiles/viewableProfiles"
|
|
|
|
import "errors"
|
|
import "slices"
|
|
|
|
var invalidRequestResponse []byte = []byte("Invalid Request")
|
|
|
|
//Outputs:
|
|
// -bool: Response successfully crafted (request was well formed)
|
|
// -bool: Identity hash of request matches our own
|
|
// -bool: Network type of request matches provided network type
|
|
// -[]byte: establishConnectionKey response
|
|
// -[32]byte: Connection key in establishConnectionKey response
|
|
// -error
|
|
func GetEstablishConnectionKeyResponse(requestBytes []byte, networkType byte)(bool, bool, bool, []byte, [32]byte, error){
|
|
|
|
isValid := helpers.VerifyNetworkType(networkType)
|
|
if (isValid == false){
|
|
networkTypeString := helpers.ConvertByteToString(networkType)
|
|
return false, false, false, nil, [32]byte{}, errors.New("GetEstablishConnectionKeyResponse called with invalid networkType: " + networkTypeString)
|
|
}
|
|
|
|
myIdentityExists, myHostPublicIdentityKey, myHostPrivateIdentityKey, err := myIdentity.GetMyPublicPrivateIdentityKeys("Host")
|
|
if (err != nil) { return false, false, false, nil, [32]byte{}, err }
|
|
if (myIdentityExists == false){
|
|
return false, false, false, nil, [32]byte{}, errors.New("GetEstablishConnectionKeyResponse called when my host identity is missing.")
|
|
}
|
|
|
|
exists, myHostIdentityHash, err := myIdentity.GetMyIdentityHash("Host")
|
|
if (err != nil) { return false, false, false, nil, [32]byte{}, err }
|
|
if (exists == false){
|
|
return false, false, false, nil, [32]byte{}, errors.New("My identity not found after being found already.")
|
|
}
|
|
|
|
recipientHost, requestIdentifier, requestNetworkType, requestorNaclKey, requestorKyberKey, err := serverRequest.ReadServerRequest_EstablishConnectionKey(requestBytes)
|
|
if (err != nil) {
|
|
// Requestor must be malicious
|
|
return false, false, false, nil, [32]byte{}, nil
|
|
}
|
|
|
|
if (recipientHost != myHostIdentityHash){
|
|
// Requestor is sending request to invalid recipient
|
|
// Requestor could be malicious or another host could be posting our clearnet/onion address as their own
|
|
// Either way, we don't continue connection
|
|
|
|
return true, false, false, nil, [32]byte{}, nil
|
|
}
|
|
if (requestNetworkType != networkType){
|
|
// Either requestor is malicious, or we recently changed our network type
|
|
// If we recently changed our network type, our old host profile may still exist on the old network
|
|
// This request could be coming from someone who has our old host profile downloaded
|
|
|
|
// The Seekia app should broadcast a disabled host profile for the old network type before switching network types
|
|
// Doing this will never solve this issue fully, because the new profile will take time to propagate to users
|
|
// Users may also connect to outdated host profiles upon startup, so this problem will always exist, which is fine.
|
|
|
|
return true, true, false, nil, [32]byte{}, nil
|
|
}
|
|
|
|
responseBytes, newConnectionKey, err := serverResponse.CreateServerResponse_EstablishConnectionKey(myHostPublicIdentityKey, myHostPrivateIdentityKey, requestIdentifier, requestorNaclKey, requestorKyberKey)
|
|
if (err != nil) { return false, false, false, nil, [32]byte{}, err }
|
|
|
|
return true, true, true, responseBytes, newConnectionKey, nil
|
|
}
|
|
|
|
//Outputs:
|
|
// -[]byte: Response Bytes
|
|
// -error
|
|
func GetServerResponseForRequest(requestBytes []byte, networkType byte, connectionKey [32]byte)([]byte, error){
|
|
|
|
isValid := helpers.VerifyNetworkType(networkType)
|
|
if (isValid == false){
|
|
networkTypeString := helpers.ConvertByteToString(networkType)
|
|
return nil, errors.New("GetServerResponseForRequest called with invalid networkType: " + networkTypeString)
|
|
}
|
|
|
|
myIdentityExists, myHostPublicIdentityKey, myHostPrivateIdentityKey, err := myIdentity.GetMyPublicPrivateIdentityKeys("Host")
|
|
if (err != nil) { return nil, err }
|
|
if (myIdentityExists == false){
|
|
return nil, errors.New("GetServerResponseForRequest called when my host identity is missing.")
|
|
}
|
|
|
|
exists, myHostIdentityHash, err := myIdentity.GetMyIdentityHash("Host")
|
|
if (err != nil) { return nil, err }
|
|
if (exists == false){
|
|
return nil, errors.New("My host identity not found after being found already.")
|
|
}
|
|
|
|
// First we decrypt the request
|
|
|
|
ableToRead, decryptedRequestBytes, err := serverRequest.ReadEncryptedRequest(requestBytes, connectionKey)
|
|
if (err != nil) { return nil, err }
|
|
if (ableToRead == false){
|
|
// Cannot read, request is malformed
|
|
return invalidRequestResponse, nil
|
|
}
|
|
|
|
// Now we read request to retrieve and verify attributes included in all requests
|
|
|
|
//TODO: Verify everything
|
|
|
|
requestRecipientHost, requestType, requestIdentifier, requestNetworkType, err := serverRequest.ReadDecryptedServerRequest_StandardData(decryptedRequestBytes)
|
|
if (err != nil){
|
|
// decryptedRequestBytes are malformed, requestor must be malicious
|
|
return invalidRequestResponse, nil
|
|
}
|
|
if (requestRecipientHost != myHostIdentityHash){
|
|
// Requestor must be malicious, because identity hash never changes during connection
|
|
return invalidRequestResponse, nil
|
|
}
|
|
if (requestNetworkType != networkType){
|
|
// Requestor must be malicious, because network type never changes during connection
|
|
return invalidRequestResponse, nil
|
|
}
|
|
|
|
// Now we get response based on the requestType
|
|
|
|
if (requestType == "GetParametersInfo"){
|
|
|
|
//TODO: Check if host is hosting parameters
|
|
|
|
allParametersTypesList := readParameters.GetAllParametersTypesList()
|
|
|
|
parametersInfoMap := make(map[string]int64)
|
|
|
|
for _, parametersType := range allParametersTypesList{
|
|
|
|
parametersFound, _, _, parametersBroadcastTime, err := parametersStorage.GetAuthorizedParameters(parametersType, networkType)
|
|
if (err != nil) { return nil, err }
|
|
if (parametersFound == false){
|
|
continue
|
|
}
|
|
parametersInfoMap[parametersType] = parametersBroadcastTime
|
|
}
|
|
|
|
responseBytes, err := serverResponse.CreateServerResponse_GetParametersInfo(myHostPublicIdentityKey, myHostPrivateIdentityKey, connectionKey, requestIdentifier, parametersInfoMap)
|
|
if (err != nil) { return nil, err }
|
|
|
|
return responseBytes, nil
|
|
}
|
|
if (requestType == "GetParameters"){
|
|
|
|
//TODO: Verify host is hosting network parameters
|
|
|
|
requestedParametersTypesList, err := serverRequest.ReadDecryptedServerRequest_GetParameters(decryptedRequestBytes)
|
|
if (err != nil){
|
|
return invalidRequestResponse, nil
|
|
}
|
|
|
|
parametersList := make([][]byte, 0)
|
|
|
|
for _, parametersType := range requestedParametersTypesList{
|
|
|
|
parametersFound, parametersBytes, _, _, err := parametersStorage.GetAuthorizedParameters(parametersType, networkType)
|
|
if (err != nil) { return nil, err }
|
|
if (parametersFound == false){
|
|
continue
|
|
}
|
|
parametersList = append(parametersList, parametersBytes)
|
|
}
|
|
|
|
responseBytes, err := serverResponse.CreateServerResponse_GetParameters(myHostPublicIdentityKey, myHostPrivateIdentityKey, connectionKey, requestIdentifier, parametersList)
|
|
if (err != nil) { return nil, err }
|
|
|
|
return responseBytes, nil
|
|
}
|
|
|
|
if (requestType == "GetProfilesInfo"){
|
|
|
|
acceptableProfileVersionsList, profileTypeToRetrieve, requestRangeStart, requestRangeEnd, requestedIdentityHashesList, requestCriteria, getNewestProfilesOnly, getViewableProfilesOnly, err := serverRequest.ReadDecryptedServerRequest_GetProfilesInfo(decryptedRequestBytes)
|
|
if (err != nil){
|
|
return invalidRequestResponse, nil
|
|
}
|
|
|
|
getRelevantIdentityHashesList := func()([][16]byte, error){
|
|
|
|
// We will find the relevant identity hashes based on either the request range or requested identities list
|
|
|
|
if (len(requestedIdentityHashesList) != 0){
|
|
|
|
return requestedIdentityHashesList, nil
|
|
}
|
|
|
|
storedProfileIdentityHashesList, err := badgerDatabase.GetAllProfileIdentityHashes(profileTypeToRetrieve)
|
|
if (err != nil) { return nil, err }
|
|
|
|
anyExist, identityHashesInRequestRange, err := byteRange.GetAllIdentityHashesInListWithinRange(requestRangeStart, requestRangeEnd, storedProfileIdentityHashesList)
|
|
if (err != nil) { return nil, err }
|
|
if (anyExist == false){
|
|
|
|
emptyList := make([][16]byte, 0)
|
|
return emptyList, nil
|
|
}
|
|
|
|
return identityHashesInRequestRange, nil
|
|
}
|
|
|
|
relevantIdentityHashesList, err := getRelevantIdentityHashesList()
|
|
if (err != nil) { return nil, err }
|
|
|
|
// We limit request to profiles hosted by host
|
|
// This is to prevent the requestor from learning information about profiles the host has downloaded
|
|
// This would be a privacy leak if the host is using Seekia to find matches/moderate.
|
|
// The requestor would know which profiles outside of the hosted range the host had downloaded
|
|
// This could potentially tell them the host's location and desires
|
|
|
|
// We reduce requested identity hashes list based on our host range
|
|
|
|
getIdentitiesInMyHostRangeList := func()([][16]byte, error){
|
|
|
|
hostModeEnabled, hostingAny, myHostRangeStart, myHostRangeEnd, err := myRanges.GetMyIdentitiesToHostRange(profileTypeToRetrieve)
|
|
if (err != nil) { return nil, err }
|
|
if (hostModeEnabled == false){
|
|
// User must have disabled host mode
|
|
emptyList := make([][16]byte, 0)
|
|
return emptyList, nil
|
|
}
|
|
if (hostingAny == false){
|
|
// We are not hosting any of the requested ProfileType
|
|
emptyList := make([][16]byte, 0)
|
|
return emptyList, nil
|
|
}
|
|
|
|
anyExist, identityHashesInMyHostRangeList, err := byteRange.GetAllIdentityHashesInListWithinRange(myHostRangeStart, myHostRangeEnd, relevantIdentityHashesList)
|
|
if (err != nil) { return nil, err }
|
|
if (anyExist == false){
|
|
emptyList := make([][16]byte, 0)
|
|
return emptyList, nil
|
|
}
|
|
|
|
return identityHashesInMyHostRangeList, nil
|
|
}
|
|
|
|
requestedIdentitiesInMyHostRangeList, err := getIdentitiesInMyHostRangeList()
|
|
if (err != nil){ return nil, err }
|
|
|
|
// Now we reduce list to make sure identities are funded
|
|
|
|
fundedIdentitiesList := make([][16]byte, 0)
|
|
|
|
for _, identityHash := range requestedIdentitiesInMyHostRangeList{
|
|
|
|
if (profileTypeToRetrieve == "Moderator"){
|
|
|
|
statusIsKnown, _, scoreIsSufficient, _, _, err := moderatorScores.GetModeratorIdentityScore(identityHash)
|
|
if (err != nil) { return nil, err }
|
|
if (statusIsKnown == false || scoreIsSufficient == false){
|
|
continue
|
|
}
|
|
|
|
} else {
|
|
|
|
// profileType == "Mate" or "Host"
|
|
|
|
statusIsKnown, isFunded, _, _, err := verifiedFundedStatus.GetVerifiedIdentityIsFundedStatus(identityHash, networkType)
|
|
if (err != nil) { return nil, err }
|
|
if (statusIsKnown == false || isFunded == false){
|
|
continue
|
|
}
|
|
}
|
|
|
|
fundedIdentitiesList = append(fundedIdentitiesList, identityHash)
|
|
}
|
|
|
|
// Now we iterate through all relevant identity hashes, find which profile(s) to send in response
|
|
// Then we add those profiles to profilesInfoMapList
|
|
|
|
profileInfoObjectsList := make([]serverResponse.ProfileInfoStruct, 0)
|
|
|
|
for _, identityHash := range fundedIdentitiesList{
|
|
|
|
//Outputs:
|
|
// -[][28]byte: List of profile hashes
|
|
// -error
|
|
getUserProfileHashesForRequest := func()([][28]byte, error){
|
|
|
|
if (getNewestProfilesOnly == true){
|
|
|
|
if (getViewableProfilesOnly == true){
|
|
|
|
profileExists, _, profileHash, _, _, _, err := viewableProfiles.GetNewestViewableUserProfile(identityHash, networkType, false, false, false)
|
|
if (err != nil) { return nil, err }
|
|
if (profileExists == false){
|
|
emptyList := make([][28]byte, 0)
|
|
return emptyList, nil
|
|
}
|
|
profileHashesList := [][28]byte{profileHash}
|
|
|
|
return profileHashesList, nil
|
|
}
|
|
// getNewestProfilesOnly = true & getViewableProfilesOnly = false
|
|
|
|
profileExists, _, profileHash, _, _, _, err := profileStorage.GetNewestUserProfile(identityHash, networkType)
|
|
if (err != nil) { return nil, err }
|
|
if (profileExists == false){
|
|
emptyList := make([][28]byte, 0)
|
|
return emptyList, nil
|
|
}
|
|
profileHashesList := [][28]byte{profileHash}
|
|
|
|
return profileHashesList, nil
|
|
}
|
|
// getNewestProfilesOnly == false
|
|
|
|
if (getViewableProfilesOnly == true){
|
|
|
|
// We will check to see if identity is banned
|
|
|
|
downloadingRequiredReviews, parametersExist, stickyStatusEstablished, identityIsViewable, err := verifiedStickyStatus.GetVerifiedIdentityIsViewableStickyStatus(identityHash, networkType)
|
|
if (err != nil) { return nil, err }
|
|
if (downloadingRequiredReviews == false || parametersExist == false || stickyStatusEstablished == false){
|
|
//We do not know if this identity is banned or not.
|
|
// We cannot seed any profiles from this user
|
|
emptyList := make([][28]byte, 0)
|
|
return emptyList, nil
|
|
}
|
|
if (identityIsViewable == false){
|
|
// Identity is banned, therefore all profiles are unviewable
|
|
emptyList := make([][28]byte, 0)
|
|
return emptyList, nil
|
|
}
|
|
}
|
|
|
|
getAllProfileHashesForIdentity := func()([][28]byte, error){
|
|
|
|
exists, profileHashesList, err := badgerDatabase.GetIdentityProfileHashesList(identityHash)
|
|
if (err != nil) { return nil, err }
|
|
if (exists == false){
|
|
emptyList := make([][28]byte, 0)
|
|
return emptyList, nil
|
|
}
|
|
return profileHashesList, nil
|
|
}
|
|
|
|
allProfileHashesForIdentityList, err := getAllProfileHashesForIdentity()
|
|
if (err != nil) { return nil, err }
|
|
|
|
if (getViewableProfilesOnly == false){
|
|
return allProfileHashesForIdentityList, nil
|
|
}
|
|
|
|
// Now we prune unviewable profiles
|
|
|
|
viewableProfileHashesList := make([][28]byte, 0)
|
|
|
|
for _, profileHash := range allProfileHashesForIdentityList{
|
|
|
|
profileIsDisabled, profileMetadataIsKnown, profileNetworkType, profileAuthor, downloadingRequiredReviews, parametersExist, stickyStatusEstablished, profileIsViewableStatus, err := verifiedStickyStatus.GetVerifiedProfileIsViewableStickyStatus(profileHash)
|
|
if (err != nil) { return nil, err }
|
|
if (profileMetadataIsKnown == false){
|
|
continue
|
|
}
|
|
if (profileNetworkType != networkType){
|
|
continue
|
|
}
|
|
if (profileIsDisabled == true){
|
|
viewableProfileHashesList = append(viewableProfileHashesList, profileHash)
|
|
continue
|
|
}
|
|
if (profileAuthor != identityHash){
|
|
return nil, errors.New("GetVerifiedProfileIsViewableStickyStatus returning different profileAuthor")
|
|
}
|
|
if (downloadingRequiredReviews == false){
|
|
// This should not happen, because this was checked earlier in function
|
|
// Maybe client changed hosted range
|
|
logger.AddLogError("Network", errors.New("Profile not in hosted range anymore."))
|
|
break
|
|
}
|
|
if (parametersExist == false){
|
|
// We cannot determine sticky consensus status for this profile.
|
|
// We shouldn't be hosting without the parameters anyway
|
|
emptyList := make([][28]byte, 0)
|
|
return emptyList, nil
|
|
}
|
|
if (stickyStatusEstablished == false){
|
|
// We cannot determine sticky consensus for this profile
|
|
// Continue to next profile
|
|
continue
|
|
}
|
|
if (profileIsViewableStatus == false){
|
|
continue
|
|
}
|
|
viewableProfileHashesList = append(viewableProfileHashesList, profileHash)
|
|
}
|
|
|
|
return viewableProfileHashesList, nil
|
|
}
|
|
|
|
userProfileHashesForRequestList, err := getUserProfileHashesForRequest()
|
|
if (err != nil) { return nil, err }
|
|
|
|
for _, profileHash := range userProfileHashesForRequestList{
|
|
|
|
if (profileTypeToRetrieve == "Mate"){
|
|
|
|
statusIsKnown, isFunded, _, _, err := verifiedFundedStatus.GetVerifiedMateProfileIsFundedStatus(profileHash)
|
|
if (err != nil) { return nil, err }
|
|
if (statusIsKnown == false || isFunded == false){
|
|
continue
|
|
}
|
|
}
|
|
|
|
profileExists, profileBytes, err := badgerDatabase.GetUserProfile(profileTypeToRetrieve, profileHash)
|
|
if (err != nil) { return nil, err }
|
|
if (profileExists == false){
|
|
// Profile must have been deleted
|
|
continue
|
|
}
|
|
|
|
ableToRead, profileHash_Retrieved, profileVersion, profileNetworkType, profileAuthor, profileBroadcastTime, profileIsDisabled, rawProfileMap, err := readProfiles.ReadProfileAndHash(false, profileBytes)
|
|
if (err != nil) { return nil, err }
|
|
if (ableToRead == false){
|
|
return nil, errors.New("Database corrupt: contains invalid " + profileTypeToRetrieve + " profile")
|
|
}
|
|
if (profileHash != profileHash_Retrieved){
|
|
return nil, errors.New("Database corrupt: Contains profile with different hash than entry key.")
|
|
}
|
|
if (profileAuthor != identityHash){
|
|
return nil, errors.New("getIdentityProfilesForRequest returning profile from a different identity hash")
|
|
}
|
|
if (profileNetworkType != networkType){
|
|
continue
|
|
}
|
|
|
|
isRequestedVersion := slices.Contains(acceptableProfileVersionsList, profileVersion)
|
|
if (isRequestedVersion == false){
|
|
// The requestor cannot accept this profile's version
|
|
// We must have a newer or older Seekia application version
|
|
continue
|
|
}
|
|
|
|
if (requestCriteria != nil){
|
|
|
|
if (profileIsDisabled == true){
|
|
// Disabled profiles will not fulfill any criteria
|
|
continue
|
|
}
|
|
|
|
criteriaIsValid, fulfillsCriteria, err := mateCriteria.CheckIfMateProfileFulfillsCriteria(true, profileVersion, rawProfileMap, requestCriteria)
|
|
if (err != nil) { return nil, err }
|
|
if (criteriaIsValid == false){
|
|
return nil, errors.New("ReadDecryptedServerRequest_GetProfilesInfo not verifying criteria.")
|
|
}
|
|
if (fulfillsCriteria == false){
|
|
continue
|
|
}
|
|
}
|
|
|
|
profileInfoObject := serverResponse.ProfileInfoStruct{
|
|
ProfileHash: profileHash,
|
|
ProfileAuthor: profileAuthor,
|
|
ProfileBroadcastTime: profileBroadcastTime,
|
|
}
|
|
|
|
profileInfoObjectsList = append(profileInfoObjectsList, profileInfoObject)
|
|
}
|
|
}
|
|
|
|
responseBytes, err := serverResponse.CreateServerResponse_GetProfilesInfo(myHostPublicIdentityKey, myHostPrivateIdentityKey, connectionKey, requestIdentifier, profileInfoObjectsList)
|
|
if (err != nil) { return nil, err }
|
|
|
|
return responseBytes, nil
|
|
}
|
|
|
|
if (requestType == "GetProfiles"){
|
|
|
|
profileTypeToRetrieve, profileHashesToRetrieveList, err := serverRequest.ReadDecryptedServerRequest_GetProfiles(decryptedRequestBytes)
|
|
if (err != nil){
|
|
// Request is malformed
|
|
return invalidRequestResponse, nil
|
|
}
|
|
|
|
// First we get all profiles that we have that the peer is requesting
|
|
// Then we prune requested profiles list
|
|
// We prune profiles whose authors are not funded, and profiles that are not funded
|
|
// We prune profiles whose author is not within our hosted range
|
|
// This is done for host privacy
|
|
// Otherwise a malicious requestor could try to find other profiles the host has
|
|
// This could fingerprint the host and make it possible to link the host identity to their mate/moderator identity/activities
|
|
|
|
getPrunedProfilesList := func()([][]byte, error){
|
|
|
|
hostModeEnabled, hostingAny, myHostRangeStart, myHostRangeEnd, err := myRanges.GetMyIdentitiesToHostRange(profileTypeToRetrieve)
|
|
if (err != nil) { return nil, err }
|
|
if (hostModeEnabled == false){
|
|
// Host must have disabled host mode in the background
|
|
emptyList := make([][]byte, 0)
|
|
return emptyList, nil
|
|
}
|
|
if (hostingAny == false){
|
|
// Host is not hosting any of the requested profiles
|
|
emptyList := make([][]byte, 0)
|
|
return emptyList, nil
|
|
}
|
|
|
|
requestedProfilesList := make([][]byte, 0)
|
|
|
|
for _, profileHash := range profileHashesToRetrieveList{
|
|
|
|
if (profileTypeToRetrieve == "Mate"){
|
|
|
|
// We make sure profile is funded
|
|
|
|
statusIsKnown, isFunded, _, _, err := verifiedFundedStatus.GetVerifiedMateProfileIsFundedStatus(profileHash)
|
|
if (err != nil) { return nil, err }
|
|
if (statusIsKnown == false || isFunded == false){
|
|
continue
|
|
}
|
|
}
|
|
|
|
profileExists, profileBytes, err := badgerDatabase.GetUserProfile(profileTypeToRetrieve, profileHash)
|
|
if (err != nil) { return nil, err }
|
|
if (profileExists == false){
|
|
// Profile could have been deleted after profile hashes response was made, or peer is malicious
|
|
// Either way, skip profile
|
|
continue
|
|
}
|
|
|
|
ableToRead, profileHash_Retrieved, _, profileNetworkType, profileAuthor, _, _, _, err := readProfiles.ReadProfileAndHash(false, profileBytes)
|
|
if (err != nil) { return nil, err }
|
|
if (ableToRead == false){
|
|
return nil, errors.New("Database corrupt: Contains invalid profile.")
|
|
}
|
|
if (profileHash_Retrieved != profileHash){
|
|
return nil, errors.New("Database corrupt: Contains profile with different hash than entry key.")
|
|
}
|
|
if (profileNetworkType != networkType){
|
|
// This should not happen unless requestor is malicious
|
|
// Requestor should only request profile hashes which we served in our GetProfilesInfo response
|
|
continue
|
|
}
|
|
|
|
if (profileTypeToRetrieve == "Mate"){
|
|
// Because hosts will provide all or no moderator/host profiles
|
|
// We only need to check if identity is in our range if profileType is Mate
|
|
|
|
isWithinRange, err := byteRange.CheckIfIdentityHashIsWithinRange(myHostRangeStart, myHostRangeEnd, profileAuthor)
|
|
if (err != nil) { return nil, err }
|
|
if (isWithinRange == false){
|
|
continue
|
|
}
|
|
}
|
|
|
|
// We check if author is funded
|
|
|
|
if (profileTypeToRetrieve == "Moderator"){
|
|
|
|
statusIsKnown, _, scoreIsSufficient, _, _, err := moderatorScores.GetModeratorIdentityScore(profileAuthor)
|
|
if (err != nil) { return nil, err }
|
|
if (statusIsKnown == false || scoreIsSufficient == false){
|
|
continue
|
|
}
|
|
|
|
} else {
|
|
|
|
// profileType == "Mate" or "Host"
|
|
|
|
statusIsKnown, isFunded, _, _, err := verifiedFundedStatus.GetVerifiedIdentityIsFundedStatus(profileAuthor, networkType)
|
|
if (err != nil) { return nil, err }
|
|
if (statusIsKnown == false || isFunded == false){
|
|
continue
|
|
}
|
|
}
|
|
|
|
requestedProfilesList = append(requestedProfilesList, profileBytes)
|
|
}
|
|
|
|
return requestedProfilesList, nil
|
|
}
|
|
|
|
prunedProfilesList, err := getPrunedProfilesList()
|
|
if (err != nil) { return nil, err }
|
|
|
|
responseBytes, err := serverResponse.CreateServerResponse_GetProfiles(myHostPublicIdentityKey, myHostPrivateIdentityKey, connectionKey, requestIdentifier, prunedProfilesList)
|
|
if (err != nil) { return nil, err }
|
|
|
|
return responseBytes, nil
|
|
}
|
|
|
|
if (requestType == "GetMessageHashesList"){
|
|
|
|
acceptableMessageVersionsList, requestInboxRangeStart, requestInboxRangeEnd, requestedInboxesList, getViewableMessagesOnly, getDecryptableMessagesOnly, err := serverRequest.ReadDecryptedServerRequest_GetMessageHashesList(decryptedRequestBytes)
|
|
if (err != nil){
|
|
return invalidRequestResponse, nil
|
|
}
|
|
|
|
getMessageHashesForResponseList := func()([][26]byte, error){
|
|
|
|
hostModeEnabled, hostingAnyInboxes, myHostedInboxesRangeStart, myHostedInboxesRangeEnd, err := myRanges.GetMyInboxesToHostRange()
|
|
if (err != nil) { return nil, err }
|
|
if (hostModeEnabled == false){
|
|
// User must have disabled host mode recently
|
|
emptyList := make([][26]byte, 0)
|
|
return emptyList, nil
|
|
}
|
|
if (hostingAnyInboxes == false){
|
|
emptyList := make([][26]byte, 0)
|
|
return emptyList, nil
|
|
}
|
|
|
|
getRequestedMessageInboxesList := func()([][10]byte, error){
|
|
|
|
if (len(requestedInboxesList) != 0){
|
|
// We will ignore range and only retrieve based on inboxes list
|
|
|
|
return requestedInboxesList, nil
|
|
}
|
|
|
|
// We will retrieve messages based on request inbox range
|
|
|
|
allMessageInboxesList, err := badgerDatabase.GetAllMessageInboxes()
|
|
if (err != nil) { return nil, err }
|
|
|
|
anyFound, intersectionInboxesList, err := byteRange.GetAllInboxesInListWithinRange(requestInboxRangeStart, requestInboxRangeEnd, allMessageInboxesList)
|
|
if (err != nil) { return nil, err }
|
|
if (anyFound == false){
|
|
emptyList := make([][10]byte, 0)
|
|
return emptyList, nil
|
|
}
|
|
|
|
return intersectionInboxesList, nil
|
|
}
|
|
|
|
requestedMessageInboxesList, err := getRequestedMessageInboxesList()
|
|
if (err != nil) { return nil, err }
|
|
|
|
messageHashesForResponseList := make([][26]byte, 0)
|
|
|
|
for _, inboxToRetrieve := range requestedMessageInboxesList{
|
|
|
|
// We check if inbox is in our range
|
|
|
|
isWithinMyRange, err := byteRange.CheckIfInboxIsWithinRange(myHostedInboxesRangeStart, myHostedInboxesRangeEnd, inboxToRetrieve)
|
|
if (err != nil) { return nil, err }
|
|
if (isWithinMyRange == false){
|
|
continue
|
|
}
|
|
|
|
anyExist, messageHashesList, err := badgerDatabase.GetChatInboxMessageHashesList(inboxToRetrieve)
|
|
if (err != nil) { return nil, err }
|
|
if (anyExist == false){
|
|
continue
|
|
}
|
|
|
|
for _, messageHash := range messageHashesList{
|
|
|
|
// We make sure each message is of an acceptable version
|
|
|
|
metadataExists, messageVersion, messageNetworkType, _, messageInbox, messageCipherKeyHash, err := contentMetadata.GetMessageMetadata(messageHash)
|
|
if (err != nil) { return nil, err }
|
|
if (metadataExists == false){
|
|
// We don't have the message stored.
|
|
continue
|
|
}
|
|
if (messageInbox != inboxToRetrieve){
|
|
return nil, errors.New("GetChatInboxMessageHashesList returning list with message of different inbox.")
|
|
}
|
|
if (messageNetworkType != networkType){
|
|
// Message belongs to a different networkType
|
|
continue
|
|
}
|
|
|
|
isAcceptable := slices.Contains(acceptableMessageVersionsList, messageVersion)
|
|
if (isAcceptable == false){
|
|
continue
|
|
}
|
|
|
|
// We make sure each message is funded
|
|
|
|
statusIsKnown, messageIsFunded, _, _, err := verifiedFundedStatus.GetVerifiedMessageIsFundedStatus(messageHash)
|
|
if (err != nil) { return nil, err }
|
|
if (statusIsKnown == false || messageIsFunded == false){
|
|
continue
|
|
}
|
|
|
|
if (getViewableMessagesOnly == true){
|
|
|
|
// We make sure message is viewable
|
|
|
|
messageMetadataIsKnown, messageNetworkType, messageInbox, _, downloadingRequiredReviews, parametersExist, statusEstablished, messageIsViewableStatus, err := verifiedStickyStatus.GetVerifiedMessageIsViewableStickyStatus(messageHash)
|
|
if (err != nil) { return nil, err }
|
|
if (messageMetadataIsKnown == false){
|
|
// Message was deleted, skip to next message
|
|
continue
|
|
}
|
|
if (messageNetworkType != networkType){
|
|
return nil, errors.New("GetVerifiedMessageIsViewableStickyStatus returning different message networkType than contentMetadata.")
|
|
}
|
|
if (messageInbox != inboxToRetrieve){
|
|
return nil, errors.New("GetVerifiedMessageIsViewableStickyStatus returning invalid message inbox")
|
|
}
|
|
if (downloadingRequiredReviews == false){
|
|
// This should only happen if hosted inbox range was changed during this operation
|
|
// All messages for this inbox will be out of range
|
|
break
|
|
}
|
|
if (parametersExist == false){
|
|
//We cannot determine sticky status for any messages. Return empty response to peer.
|
|
emptyList := make([][26]byte, 0)
|
|
return emptyList, nil
|
|
}
|
|
if (statusEstablished == false){
|
|
// We do not know sticky consensus for message. Skip message.
|
|
continue
|
|
}
|
|
if (messageIsViewableStatus == false){
|
|
continue
|
|
}
|
|
}
|
|
|
|
if (getDecryptableMessagesOnly == true){
|
|
|
|
// We make sure at least 1 review/report with valid cipher key exists for message
|
|
checkIfMessageCipherKeyExists := func()(bool, error){
|
|
|
|
cipherKeyFound, _, err := reportStorage.GetMessageCipherKeyFromAnyReport(messageHash, messageNetworkType, messageCipherKeyHash)
|
|
if (err != nil) { return false, err }
|
|
if (cipherKeyFound == true){
|
|
return true, nil
|
|
}
|
|
|
|
cipherKeyFound, _, err = reviewStorage.GetMessageCipherKeyFromAnyReview(messageHash, messageNetworkType, messageCipherKeyHash)
|
|
if (err != nil) { return false, err }
|
|
if (cipherKeyFound == true){
|
|
return true, nil
|
|
}
|
|
|
|
return false, nil
|
|
}
|
|
|
|
messageCipherKeyExists, err := checkIfMessageCipherKeyExists()
|
|
if (err != nil) { return nil, err }
|
|
if (messageCipherKeyExists == false){
|
|
continue
|
|
}
|
|
}
|
|
|
|
messageHashesForResponseList = append(messageHashesForResponseList, messageHash)
|
|
}
|
|
}
|
|
|
|
return messageHashesForResponseList, nil
|
|
}
|
|
|
|
messageHashesForResponseList, err := getMessageHashesForResponseList()
|
|
if (err != nil) { return nil, err }
|
|
|
|
responseBytes, err := serverResponse.CreateServerResponse_GetMessageHashesList(myHostPublicIdentityKey, myHostPrivateIdentityKey, connectionKey, requestIdentifier, messageHashesForResponseList)
|
|
if (err != nil) { return nil, err }
|
|
|
|
return responseBytes, nil
|
|
}
|
|
if (requestType == "GetMessages"){
|
|
|
|
requestedMessageHashesList, err := serverRequest.ReadDecryptedServerRequest_GetMessages(decryptedRequestBytes)
|
|
if (err != nil) { return nil, err }
|
|
|
|
getMessagesListForResponse := func()([][]byte, error){
|
|
|
|
hostModeEnabled, hostingAny, myInboxRangeStart, myInboxRangeEnd, err := myRanges.GetMyInboxesToHostRange()
|
|
if (err != nil) { return nil, err }
|
|
if (hostModeEnabled == false){
|
|
// User must have disabled host mode
|
|
emptyList := make([][]byte, 0)
|
|
return emptyList, nil
|
|
}
|
|
|
|
if (hostingAny == false){
|
|
// We are not hosting any messages
|
|
emptyList := make([][]byte, 0)
|
|
return emptyList, nil
|
|
}
|
|
|
|
messagesListForResponse := make([][]byte, 0)
|
|
|
|
for _, messageHash := range requestedMessageHashesList{
|
|
|
|
// We make sure each message is funded
|
|
|
|
statusIsKnown, messageIsFunded, _, _, err := verifiedFundedStatus.GetVerifiedMessageIsFundedStatus(messageHash)
|
|
if (err != nil) { return nil, err }
|
|
if (statusIsKnown == false || messageIsFunded == false){
|
|
continue
|
|
}
|
|
|
|
messageExists, messageBytes, err := badgerDatabase.GetChatMessage(messageHash)
|
|
if (err != nil) { return nil, err }
|
|
if (messageExists == false){
|
|
continue
|
|
}
|
|
|
|
ableToRead, currentMessageHash, _, messageNetworkType, messageInbox, _, _, _, _, _, _, err := readMessages.ReadChatMessagePublicDataAndHash(false, messageBytes)
|
|
if (err != nil) { return nil, err }
|
|
if (ableToRead == false){
|
|
return nil, errors.New("Database corrupt: Contains malformed message.")
|
|
}
|
|
if (messageHash != currentMessageHash){
|
|
return nil, errors.New("Database corrupt: Contains message with mismatched messageHash entry key")
|
|
}
|
|
if (messageNetworkType != networkType){
|
|
// This should not happen unless requestor is malicious
|
|
// The requestor should only requests messages which we already said were on the connection networkType.
|
|
continue
|
|
}
|
|
|
|
isWithinMyRange, err := byteRange.CheckIfInboxIsWithinRange(myInboxRangeStart, myInboxRangeEnd, messageInbox)
|
|
if (err != nil) { return nil, err }
|
|
if (isWithinMyRange == false){
|
|
continue
|
|
}
|
|
|
|
messagesListForResponse = append(messagesListForResponse, messageBytes)
|
|
}
|
|
|
|
return messagesListForResponse, nil
|
|
}
|
|
|
|
messagesListForResponse, err := getMessagesListForResponse()
|
|
if (err != nil) { return nil, err }
|
|
|
|
responseBytes, err := serverResponse.CreateServerResponse_GetMessages(myHostPublicIdentityKey, myHostPrivateIdentityKey, connectionKey, requestIdentifier, messagesListForResponse)
|
|
if (err != nil) { return nil, err }
|
|
|
|
return responseBytes, nil
|
|
}
|
|
if (requestType == "GetIdentityReviewsInfo"){
|
|
|
|
acceptableReviewVersions, identityTypeToRetrieve, requestRangeStart, requestRangeEnd, requestedReviewedIdentityHashesList, requestedReviewersList, err := serverRequest.ReadDecryptedServerRequest_GetIdentityReviewsInfo(decryptedRequestBytes)
|
|
if (err != nil){
|
|
return invalidRequestResponse, nil
|
|
}
|
|
|
|
getReviewsInfoMap := func()(map[[29]byte][]byte, error){
|
|
|
|
hostModeEnabled, hostingAny, myIdentityRangeStart, myIdentityRangeEnd, err := myRanges.GetMyIdentitiesToHostRange(identityTypeToRetrieve)
|
|
if (err != nil) { return nil, err }
|
|
if (hostModeEnabled == false){
|
|
// We must have turned off host mode recently
|
|
emptyReviewsInfoMap := make(map[[29]byte][]byte)
|
|
return emptyReviewsInfoMap, nil
|
|
}
|
|
if (hostingAny == false){
|
|
emptyReviewsInfoMap := make(map[[29]byte][]byte)
|
|
return emptyReviewsInfoMap, nil
|
|
}
|
|
|
|
// We include identity, profile and attribute reviews
|
|
|
|
relevantReviewHashesList := make([][29]byte, 0)
|
|
|
|
allReviewedIdentityHashesList, err := badgerDatabase.GetAllReviewedIdentityHashes()
|
|
if (err != nil) { return nil, err }
|
|
|
|
for _, identityHash := range allReviewedIdentityHashesList{
|
|
|
|
anyExist, reviewHashesList, err := badgerDatabase.GetIdentityReviewsList(identityHash)
|
|
if (err != nil) { return nil, err }
|
|
if (anyExist == true){
|
|
relevantReviewHashesList = append(relevantReviewHashesList, reviewHashesList...)
|
|
}
|
|
}
|
|
|
|
allReviewedProfileHashesList, err := badgerDatabase.GetAllReviewedProfileHashes()
|
|
if (err != nil) { return nil, err }
|
|
|
|
for _, profileHash := range allReviewedProfileHashesList{
|
|
|
|
anyExist, reviewHashesList, err := badgerDatabase.GetProfileReviewsList(profileHash)
|
|
if (err != nil) { return nil, err }
|
|
if (anyExist == true){
|
|
relevantReviewHashesList = append(relevantReviewHashesList, reviewHashesList...)
|
|
}
|
|
}
|
|
|
|
allReviewedAttributeHashesList, err := badgerDatabase.GetAllReviewedProfileAttributeHashes()
|
|
if (err != nil) { return nil, err }
|
|
|
|
for _, attributeHash := range allReviewedAttributeHashesList{
|
|
|
|
anyExist, reviewHashesList, err := badgerDatabase.GetProfileAttributeReviewsList(attributeHash)
|
|
if (err != nil) { return nil, err }
|
|
if (anyExist == true){
|
|
relevantReviewHashesList = append(relevantReviewHashesList, reviewHashesList...)
|
|
}
|
|
}
|
|
|
|
// Map structure: Review hash -> Reviewed hash
|
|
reviewsInfoMap := make(map[[29]byte][]byte)
|
|
|
|
for _, reviewHash := range relevantReviewHashesList{
|
|
|
|
reviewExists, reviewBytes, err := badgerDatabase.GetReview(reviewHash)
|
|
if (err != nil) { return nil, err }
|
|
if (reviewExists == false){
|
|
// Review must have been deleted automatically.
|
|
// The database entry that referenced the review will be deleted automatically
|
|
continue
|
|
}
|
|
|
|
ableToRead, currentReviewHash, reviewVersion, reviewNetworkType, reviewerIdentityHash, _, reviewType, reviewedHash, _, _, err := readReviews.ReadReviewAndHash(false, reviewBytes)
|
|
if (err != nil) { return nil, err }
|
|
if (ableToRead == false){
|
|
return nil, errors.New("Database corrupt: Contains invalid review.")
|
|
}
|
|
if (reviewHash != currentReviewHash){
|
|
return nil, errors.New("Database corrupt: Review entry key does not match review hash")
|
|
}
|
|
isAcceptableVersion := slices.Contains(acceptableReviewVersions, reviewVersion)
|
|
if (isAcceptableVersion == false){
|
|
// Review is of a different version than requestor can accept
|
|
// We must have a different Seekia app version than them.
|
|
continue
|
|
}
|
|
if (reviewNetworkType != networkType){
|
|
// Review belongs to a different networkType
|
|
continue
|
|
}
|
|
|
|
if (len(requestedReviewersList) != 0){
|
|
isInRequestedList := slices.Contains(requestedReviewersList, reviewerIdentityHash)
|
|
if (isInRequestedList == false){
|
|
continue
|
|
}
|
|
}
|
|
|
|
statusIsKnown, _, scoreIsSufficient, _, _, err := moderatorScores.GetModeratorIdentityScore(reviewerIdentityHash)
|
|
if (err != nil) { return nil, err }
|
|
if (statusIsKnown == false || scoreIsSufficient == false){
|
|
continue
|
|
}
|
|
|
|
//Outputs:
|
|
// -bool: Review is malicious
|
|
// -bool: Reviewed identity hash is known
|
|
// -[16]byte: Reviewed identity hash
|
|
// -error
|
|
getReviewedIdentityHash := func()(bool, bool, [16]byte, error){
|
|
|
|
if (reviewType == "Identity"){
|
|
|
|
if (len(reviewedHash) != 16){
|
|
reviewedHashHex := encoding.EncodeBytesToHexString(reviewedHash)
|
|
return false, false, [16]byte{}, errors.New("ReadReview returning invalid reviewedHash length for Identity review: " + reviewedHashHex)
|
|
}
|
|
|
|
reviewedIdentityHash := [16]byte(reviewedHash)
|
|
|
|
return false, true, reviewedIdentityHash, nil
|
|
}
|
|
if (reviewType == "Profile"){
|
|
|
|
if (len(reviewedHash) != 28){
|
|
reviewedHashHex := encoding.EncodeBytesToHexString(reviewedHash)
|
|
return false, false, [16]byte{}, errors.New("ReadReview returning invalid reviewedHash length for Profile review: " + reviewedHashHex)
|
|
}
|
|
|
|
reviewedProfileHash := [28]byte(reviewedHash)
|
|
|
|
metadataExists, _, profileNetworkType, profileAuthor, _, _, _, _, err := contentMetadata.GetProfileMetadata(reviewedProfileHash)
|
|
if (err != nil) { return false, false, [16]byte{}, err }
|
|
if (metadataExists == false){
|
|
return false, false, [16]byte{}, nil
|
|
}
|
|
if (profileNetworkType != reviewNetworkType){
|
|
// The review is reviewing a profile from a different networkType
|
|
// The review author must be malicious
|
|
return true, false, [16]byte{}, nil
|
|
}
|
|
|
|
return false, true, profileAuthor, nil
|
|
}
|
|
if (reviewType == "Attribute"){
|
|
|
|
if (len(reviewedHash) != 27){
|
|
reviewedHashHex := encoding.EncodeBytesToHexString(reviewedHash)
|
|
return false, false, [16]byte{}, errors.New("ReadReview returning invalid reviewedHash length for Attribute review: " + reviewedHashHex)
|
|
}
|
|
|
|
reviewedAttributeHash := [27]byte(reviewedHash)
|
|
|
|
attributeMetadataFound, _, authorIdentityHash, attributeNetworkType, _, err := profileStorage.GetProfileAttributeMetadata(reviewedAttributeHash)
|
|
if (err != nil) { return false, false, [16]byte{}, err }
|
|
if (attributeMetadataFound == false){
|
|
return false, false, [16]byte{}, nil
|
|
}
|
|
if (attributeNetworkType != reviewNetworkType){
|
|
// The review is reviewing an attribute from a different networkType
|
|
// The review author must be malicious
|
|
return true, false, [16]byte{}, nil
|
|
}
|
|
|
|
return false, true, authorIdentityHash, nil
|
|
}
|
|
|
|
return false, false, [16]byte{}, errors.New("getReviewedIdentityHash reached during GetIdentityReviewsInfo response craft with invalid reviewType: " + reviewType)
|
|
}
|
|
|
|
reviewIsMalicious, reviewedIdentityHashIsKnown, reviewedIdentityHash, err := getReviewedIdentityHash()
|
|
if (err != nil) { return nil, err }
|
|
if (reviewIsMalicious == true){
|
|
// Review is malicious. We will not seed reviews which are known to be malicious
|
|
// TODO: Skipping these kinds of reviews could be a fingerprinting risk?
|
|
continue
|
|
}
|
|
if (reviewedIdentityHashIsKnown == false){
|
|
// We cannot seed reviews whose reviewed identity hash is not known.
|
|
continue
|
|
}
|
|
|
|
reviewedIdentityType, err := identity.GetIdentityTypeFromIdentityHash(reviewedIdentityHash)
|
|
if (err != nil){ return nil, err }
|
|
if (reviewedIdentityType != identityTypeToRetrieve){
|
|
continue
|
|
}
|
|
|
|
if (len(requestedReviewedIdentityHashesList) != 0){
|
|
|
|
// We make sure all reviewed identity hashes are within this list
|
|
|
|
isWithinList := slices.Contains(requestedReviewedIdentityHashesList, reviewedIdentityHash)
|
|
if (isWithinList == false){
|
|
continue
|
|
}
|
|
} else {
|
|
|
|
identityIsWithinRequestRange, err := byteRange.CheckIfIdentityHashIsWithinRange(requestRangeStart, requestRangeEnd, reviewedIdentityHash)
|
|
if (err != nil) { return nil, err }
|
|
if (identityIsWithinRequestRange == false){
|
|
continue
|
|
}
|
|
}
|
|
|
|
// We make sure identity is within our range
|
|
|
|
isWithinMyRange, err := byteRange.CheckIfIdentityHashIsWithinRange(myIdentityRangeStart, myIdentityRangeEnd, reviewedIdentityHash)
|
|
if (err != nil) { return nil, err }
|
|
if (isWithinMyRange == false){
|
|
continue
|
|
}
|
|
|
|
// We make sure reviewed identity is funded
|
|
|
|
if (identityTypeToRetrieve == "Moderator"){
|
|
|
|
statusIsKnown, _, scoreIsSufficient, _, _, err := moderatorScores.GetModeratorIdentityScore(reviewedIdentityHash)
|
|
if (err != nil) { return nil, err }
|
|
if (statusIsKnown == false || scoreIsSufficient == false){
|
|
continue
|
|
}
|
|
|
|
} else {
|
|
|
|
// identityTypeToRetrieve == "Mate" or "Host"
|
|
|
|
statusIsKnown, isFunded, _, _, err := verifiedFundedStatus.GetVerifiedIdentityIsFundedStatus(reviewedIdentityHash, networkType)
|
|
if (err != nil) { return nil, err }
|
|
if (statusIsKnown == false || isFunded == false){
|
|
continue
|
|
}
|
|
}
|
|
|
|
if (identityTypeToRetrieve == "Mate" && reviewType == "Profile"){
|
|
|
|
// We make sure the mate profile is funded
|
|
|
|
if (len(reviewedHash) != 28){
|
|
reviewedHashHex := encoding.EncodeBytesToHexString(reviewedHash)
|
|
return nil, errors.New("ReadReview returning invalid length reviewedHash for Profile review: " + reviewedHashHex)
|
|
}
|
|
|
|
reviewedProfileHash := [28]byte(reviewedHash)
|
|
|
|
statusIsKnown, isFunded, _, _, err := verifiedFundedStatus.GetVerifiedMateProfileIsFundedStatus(reviewedProfileHash)
|
|
if (err != nil) { return nil, err }
|
|
if (statusIsKnown == false || isFunded == false){
|
|
continue
|
|
}
|
|
|
|
} else if (identityTypeToRetrieve == "Mate" && reviewType == "Attribute"){
|
|
|
|
// We make sure at least 1 profile with this attribute is funded
|
|
|
|
checkIfAnyAttributeProfileIsFunded := func()(bool, error){
|
|
|
|
if (len(reviewedHash) != 27){
|
|
reviewedHashHex := encoding.EncodeBytesToHexString(reviewedHash)
|
|
return false, errors.New("ReadReview returning invalid length reviewedHash for attribute review: " + reviewedHashHex)
|
|
}
|
|
|
|
reviewedAttributeHash := [27]byte(reviewedHash)
|
|
|
|
anyExist, attributeProfileHashesList, err := badgerDatabase.GetAttributeProfilesList(reviewedAttributeHash)
|
|
if (err != nil) { return false, err }
|
|
if (anyExist == false){
|
|
return false, nil
|
|
}
|
|
|
|
for _, profileHash := range attributeProfileHashesList{
|
|
|
|
statusIsKnown, isFunded, _, _, err := verifiedFundedStatus.GetVerifiedMateProfileIsFundedStatus(profileHash)
|
|
if (err != nil) { return false, err }
|
|
if (statusIsKnown == true && isFunded == true){
|
|
return true, nil
|
|
}
|
|
}
|
|
return false, nil
|
|
}
|
|
|
|
anyAttributeProfileIsFunded, err := checkIfAnyAttributeProfileIsFunded()
|
|
if (err != nil) { return nil, err }
|
|
if (anyAttributeProfileIsFunded == false){
|
|
continue
|
|
}
|
|
}
|
|
|
|
reviewsInfoMap[reviewHash] = reviewedHash
|
|
}
|
|
|
|
return reviewsInfoMap, nil
|
|
}
|
|
|
|
reviewsInfoMap, err := getReviewsInfoMap()
|
|
if (err != nil) { return nil, err }
|
|
|
|
responseBytes, err := serverResponse.CreateServerResponse_GetIdentityReviewsInfo(myHostPublicIdentityKey, myHostPrivateIdentityKey, connectionKey, requestIdentifier, reviewsInfoMap)
|
|
if (err != nil) { return nil, err }
|
|
|
|
return responseBytes, nil
|
|
}
|
|
if (requestType == "GetMessageReviewsInfo"){
|
|
|
|
acceptableReviewVersions, requestRangeStart, requestRangeEnd, requestedReviewedMessageHashesList, requestedReviewersList, err := serverRequest.ReadDecryptedServerRequest_GetMessageReviewsInfo(decryptedRequestBytes)
|
|
if (err != nil){
|
|
return invalidRequestResponse, nil
|
|
}
|
|
|
|
getReviewsInfoMap := func()(map[[29]byte][26]byte, error){
|
|
|
|
hostModeEnabled, hostingAnyInboxes, myInboxRangeStart, myInboxRangeEnd, err := myRanges.GetMyInboxesToHostRange()
|
|
if (err != nil) { return nil, err }
|
|
if (hostModeEnabled == false){
|
|
// Host mode must have been disabled recently
|
|
reviewsInfoMap := make(map[[29]byte][26]byte)
|
|
return reviewsInfoMap, nil
|
|
}
|
|
if (hostingAnyInboxes == false){
|
|
// We are not hosting any messages/ message reviews
|
|
reviewsInfoMap := make(map[[29]byte][26]byte)
|
|
return reviewsInfoMap, nil
|
|
}
|
|
|
|
getRelevantMessageHashesList := func()([][26]byte, error){
|
|
|
|
if (len(requestedReviewedMessageHashesList) != 0){
|
|
|
|
// We only want to return reviews that review message hashes that are within the requestedReviewedMessageHashesList
|
|
|
|
return requestedReviewedMessageHashesList, nil
|
|
}
|
|
|
|
// We want to share reviews which review all reviewed message hashes
|
|
// We will reduce based on requested range later
|
|
|
|
allReviewedMessageHashesList, err := badgerDatabase.GetAllReviewedMessageHashes()
|
|
if (err != nil) { return nil, err }
|
|
|
|
return allReviewedMessageHashesList, nil
|
|
}
|
|
|
|
relevantMessageHashesList, err := getRelevantMessageHashesList()
|
|
if (err != nil){ return nil, err }
|
|
|
|
relevantReviewHashesList := make([][29]byte, 0)
|
|
|
|
for _, messageHash := range relevantMessageHashesList{
|
|
|
|
anyExist, reviewHashesList, err := badgerDatabase.GetMessageReviewsList(messageHash)
|
|
if (err != nil) { return nil, err }
|
|
if (anyExist == true){
|
|
relevantReviewHashesList = append(relevantReviewHashesList, reviewHashesList...)
|
|
}
|
|
}
|
|
|
|
// Map Structure: Review hash -> Reviewed message hash
|
|
reviewsInfoMap := make(map[[29]byte][26]byte)
|
|
|
|
for _, reviewHash := range relevantReviewHashesList{
|
|
|
|
reviewExists, reviewBytes, err := badgerDatabase.GetReview(reviewHash)
|
|
if (err != nil) { return nil, err }
|
|
if (reviewExists == false){
|
|
continue
|
|
}
|
|
|
|
ableToRead, currentReviewHash, reviewVersion, reviewNetworkType, reviewerIdentityHash, _, reviewType, reviewedHash, _, _, err := readReviews.ReadReviewAndHash(false, reviewBytes)
|
|
if (err != nil) { return nil, err }
|
|
if (ableToRead == false){
|
|
return nil, errors.New("Database corrupt: Contains invalid review.")
|
|
}
|
|
if (reviewHash != currentReviewHash){
|
|
return nil, errors.New("Database corrupt: Review entry key does not match review hash")
|
|
}
|
|
isAcceptableVersion := slices.Contains(acceptableReviewVersions, reviewVersion)
|
|
if (isAcceptableVersion == false){
|
|
// Review is of a different version than requestor can accept
|
|
// We must have a different Seekia app version than them.
|
|
continue
|
|
}
|
|
if (reviewNetworkType != networkType){
|
|
// Review belongs to a different networkType
|
|
continue
|
|
}
|
|
|
|
if (len(requestedReviewersList) != 0){
|
|
isInRequestedList := slices.Contains(requestedReviewersList, reviewerIdentityHash)
|
|
if (isInRequestedList == false){
|
|
continue
|
|
}
|
|
}
|
|
|
|
if (reviewType != "Message"){
|
|
return nil, errors.New("Database corrupt: Message reviews list contains non-message review")
|
|
}
|
|
|
|
// We will reduce the requested reviews based on requested inbox range
|
|
|
|
if (len(reviewedHash) != 26){
|
|
reviewedHashHex := encoding.EncodeBytesToHexString(reviewedHash)
|
|
return nil, errors.New("ReadReview returning invalid length reviewedHash for Message review: " + reviewedHashHex)
|
|
}
|
|
|
|
reviewedMessageHash := [26]byte(reviewedHash)
|
|
|
|
metadataExists, _, messageNetworkType, _, messageInbox, _, err := contentMetadata.GetMessageMetadata(reviewedMessageHash)
|
|
if (err != nil){ return nil, err }
|
|
if (metadataExists == false){
|
|
// We cannot seed reviews for messages whose metadata we do not know
|
|
continue
|
|
}
|
|
if (messageNetworkType != reviewNetworkType){
|
|
// The review author must be malicious
|
|
continue
|
|
}
|
|
|
|
isWithinMyRange, err := byteRange.CheckIfInboxIsWithinRange(myInboxRangeStart, myInboxRangeEnd, messageInbox)
|
|
if (err != nil) { return nil, err }
|
|
if (isWithinMyRange == false){
|
|
continue
|
|
}
|
|
|
|
// We make sure message inbox is within requested inbox range
|
|
|
|
isWithinRequestRange, err := byteRange.CheckIfInboxIsWithinRange(requestRangeStart, requestRangeEnd, messageInbox)
|
|
if (err != nil) { return nil, err }
|
|
if (isWithinRequestRange == false){
|
|
continue
|
|
}
|
|
|
|
// We make sure message is funded
|
|
|
|
statusIsKnown, messageIsFunded, _, _, err := verifiedFundedStatus.GetVerifiedMessageIsFundedStatus(reviewedMessageHash)
|
|
if (err != nil) { return nil, err }
|
|
if (statusIsKnown == false || messageIsFunded == false){
|
|
continue
|
|
}
|
|
|
|
reviewsInfoMap[reviewHash] = reviewedMessageHash
|
|
}
|
|
|
|
return reviewsInfoMap, nil
|
|
}
|
|
|
|
reviewsInfoMap, err := getReviewsInfoMap()
|
|
if (err != nil) { return nil, err }
|
|
|
|
responseBytes, err := serverResponse.CreateServerResponse_GetMessageReviewsInfo(myHostPublicIdentityKey, myHostPrivateIdentityKey, connectionKey, requestIdentifier, reviewsInfoMap)
|
|
if (err != nil) { return nil, err }
|
|
|
|
return responseBytes, nil
|
|
}
|
|
if (requestType == "GetReviews"){
|
|
|
|
requestedReviewHashesList, err := serverRequest.ReadDecryptedServerRequest_GetReviews(decryptedRequestBytes)
|
|
if (err != nil) { return nil, err }
|
|
|
|
getReviewsListForResponse := func()([][]byte, error){
|
|
|
|
// We will reduce reviews to only our hosted range
|
|
// This is done to prevent fingerprinting
|
|
// We also make sure all reviewers, reviewed content, and reviewed identities are funded
|
|
|
|
reviewsListForResponse := make([][]byte, 0)
|
|
|
|
for _, reviewHash := range requestedReviewHashesList{
|
|
|
|
reviewExists, reviewBytes, err := badgerDatabase.GetReview(reviewHash)
|
|
if (err != nil) { return nil, err }
|
|
if (reviewExists == false){
|
|
continue
|
|
}
|
|
|
|
ableToRead, currentReviewHash, _, reviewNetworkType, reviewerIdentityHash, _, reviewType, reviewedHash, _, _, err := readReviews.ReadReviewAndHash(false, reviewBytes)
|
|
if (err != nil) { return nil, err }
|
|
if (ableToRead == false){
|
|
return nil, errors.New("Database corrupt: Contains invalid review.")
|
|
}
|
|
if (reviewHash != currentReviewHash){
|
|
return nil, errors.New("Database corrupt: Contains review with mismatched reviewHash entry key")
|
|
}
|
|
if (reviewNetworkType != networkType){
|
|
// Requestor must be malicious
|
|
// They should only request reviews which we told them were on the connection networkType
|
|
continue
|
|
}
|
|
|
|
statusIsKnown, _, scoreIsSufficient, _, _, err := moderatorScores.GetModeratorIdentityScore(reviewerIdentityHash)
|
|
if (err != nil) { return nil, err }
|
|
if (statusIsKnown == false || scoreIsSufficient == false){
|
|
continue
|
|
}
|
|
|
|
if (reviewType == "Message"){
|
|
|
|
if (len(reviewedHash) != 26){
|
|
reviewedHashHex := encoding.EncodeBytesToHexString(reviewedHash)
|
|
return nil, errors.New("ReadReview returning invalid length reviewedHash for Message review: " + reviewedHashHex)
|
|
}
|
|
|
|
reviewedMessageHash := [26]byte(reviewedHash)
|
|
|
|
metadataExists, _, messageNetworkType, _, messageInbox, _, err := contentMetadata.GetMessageMetadata(reviewedMessageHash)
|
|
if (err != nil) { return nil, err }
|
|
if (metadataExists == false){
|
|
// We cannot serve reviews whose reviewed content we do not have saved
|
|
continue
|
|
}
|
|
if (messageNetworkType != reviewNetworkType){
|
|
// Review author must be malicious
|
|
// We will not serve malicious reviews
|
|
// Requestor must be malicious, because we would have already checked for this condition
|
|
// before we offered this review to requestor
|
|
continue
|
|
}
|
|
|
|
hostModeEnabled, isWithinMyRange, err := myRanges.CheckIfMessageInboxIsWithinMyHostedRange(messageInbox)
|
|
if (err != nil) { return nil, err }
|
|
if (hostModeEnabled == false){
|
|
// Host mode must have been disabled after earlier check.
|
|
emptyList := make([][]byte, 0)
|
|
return emptyList, nil
|
|
}
|
|
if (isWithinMyRange == false){
|
|
continue
|
|
}
|
|
|
|
statusIsKnown, messageIsFunded, _, _, err := verifiedFundedStatus.GetVerifiedMessageIsFundedStatus(reviewedMessageHash)
|
|
if (err != nil) { return nil, err }
|
|
if (statusIsKnown == false || messageIsFunded == false){
|
|
continue
|
|
}
|
|
|
|
} else {
|
|
// reviewType == "Identity" or "Profile" or "Attribute"
|
|
|
|
//Outputs:
|
|
// -bool: Review is malicious
|
|
// -bool: Identity hash is known
|
|
// -[16]byte: Reviewed identity hash
|
|
// -error
|
|
getReviewedIdentityHash := func()(bool, bool, [16]byte, error){
|
|
|
|
if (reviewType == "Identity"){
|
|
|
|
if (len(reviewedHash) != 16){
|
|
reviewedHashHex := encoding.EncodeBytesToHexString(reviewedHash)
|
|
return false, false, [16]byte{}, errors.New("ReadReview returning invalid length reviewedHash for Identity review: " + reviewedHashHex)
|
|
}
|
|
|
|
reviewedIdentityHash := [16]byte(reviewedHash)
|
|
|
|
return false, true, reviewedIdentityHash, nil
|
|
}
|
|
|
|
if (reviewType == "Profile"){
|
|
|
|
if (len(reviewedHash) != 28){
|
|
reviewedHashHex := encoding.EncodeBytesToHexString(reviewedHash)
|
|
return false, false, [16]byte{}, errors.New("ReadReview returning invalid length reviewedHash for Profile review: " + reviewedHashHex)
|
|
}
|
|
|
|
reviewedProfileHash := [28]byte(reviewedHash)
|
|
|
|
metadataExists, _, profileNetworkType, profileAuthor, _, _, _, _, err := contentMetadata.GetProfileMetadata(reviewedProfileHash)
|
|
if (err != nil) { return false, false, [16]byte{}, err }
|
|
if (metadataExists == false){
|
|
return false, false, [16]byte{}, nil
|
|
}
|
|
if (profileNetworkType != reviewNetworkType){
|
|
// Review author must be malicious
|
|
return true, false, [16]byte{}, nil
|
|
}
|
|
|
|
return false, true, profileAuthor, nil
|
|
}
|
|
if (reviewType == "Attribute"){
|
|
|
|
if (len(reviewedHash) != 27){
|
|
reviewedHashHex := encoding.EncodeBytesToHexString(reviewedHash)
|
|
return false, false, [16]byte{}, errors.New("ReadReview returning invalid length reviewedHash for Attribute review: " + reviewedHashHex)
|
|
}
|
|
|
|
reviewedAttributeHash := [27]byte(reviewedHash)
|
|
|
|
attributeMetadataFound, _, authorIdentityHash, attributeNetworkType, _, err := profileStorage.GetProfileAttributeMetadata(reviewedAttributeHash)
|
|
if (err != nil) { return false, false, [16]byte{}, err }
|
|
if (attributeMetadataFound == false){
|
|
return false, false, [16]byte{}, nil
|
|
}
|
|
if (attributeNetworkType != reviewNetworkType){
|
|
// The review is reviewing an attribute from a different networkType
|
|
// The review author must be malicious
|
|
return true, true, [16]byte{}, nil
|
|
}
|
|
|
|
return false, true, authorIdentityHash, nil
|
|
}
|
|
|
|
return false, false, [16]byte{}, errors.New("ReadReview returning invalid reviewType: " + reviewType)
|
|
}
|
|
|
|
reviewIsMalicious, metadataExists, reviewedIdentityHash, err := getReviewedIdentityHash()
|
|
if (err != nil) { return nil, err }
|
|
if (reviewIsMalicious == true){
|
|
// We will not serve malicious reviews
|
|
// Requestor must be malicious, because we should have already checked for this before
|
|
// offering a review hash in the Get...ReviewsInfo responses
|
|
continue
|
|
}
|
|
if (metadataExists == false){
|
|
// We cannot seed reviews whose reviewed identity hash we do not know
|
|
continue
|
|
}
|
|
|
|
hostModeEnabled, isInMyRange, err := myRanges.CheckIfIdentityHashIsWithinMyHostedRange(reviewedIdentityHash)
|
|
if (err != nil) { return nil, err }
|
|
if (hostModeEnabled == false){
|
|
// Host mode must have been disabled after earlier check. Return empty list.
|
|
emptyList := make([][]byte, 0)
|
|
return emptyList, nil
|
|
}
|
|
|
|
if (isInMyRange == false){
|
|
continue
|
|
}
|
|
|
|
// We make sure reviewed identity is funded
|
|
|
|
reviewedIdentityType, err := identity.GetIdentityTypeFromIdentityHash(reviewedIdentityHash)
|
|
if (err != nil) { return nil, err }
|
|
if (reviewedIdentityType == "Moderator"){
|
|
|
|
statusIsKnown, _, scoreIsSufficient, _, _, err := moderatorScores.GetModeratorIdentityScore(reviewedIdentityHash)
|
|
if (err != nil) { return nil, err }
|
|
if (statusIsKnown == false || scoreIsSufficient == false){
|
|
continue
|
|
}
|
|
|
|
} else {
|
|
|
|
// reviewedIdentityType == "Mate" or "Host"
|
|
|
|
statusIsKnown, isFunded, _, _, err := verifiedFundedStatus.GetVerifiedIdentityIsFundedStatus(reviewedIdentityHash, networkType)
|
|
if (err != nil) { return nil, err }
|
|
if (statusIsKnown == false || isFunded == false){
|
|
continue
|
|
}
|
|
}
|
|
|
|
if (reviewedIdentityType == "Mate" && reviewType == "Profile"){
|
|
|
|
// We make sure profile is funded
|
|
|
|
if (len(reviewedHash) != 28){
|
|
reviewedHashHex := encoding.EncodeBytesToHexString(reviewedHash)
|
|
return nil, errors.New("ReadReview returning invalid length reviewedHash for Profile review: " + reviewedHashHex)
|
|
}
|
|
|
|
reviewedProfileHash := [28]byte(reviewedHash)
|
|
|
|
statusIsKnown, isFunded, _, _, err := verifiedFundedStatus.GetVerifiedMateProfileIsFundedStatus(reviewedProfileHash)
|
|
if (err != nil) { return nil, err }
|
|
if (statusIsKnown == false || isFunded == false){
|
|
continue
|
|
}
|
|
|
|
} else if (reviewedIdentityType == "Mate" && reviewType == "Attribute"){
|
|
|
|
// We make sure at least 1 profile with this attribute is funded
|
|
|
|
checkIfAnyAttributeProfileIsFunded := func()(bool, error){
|
|
|
|
if (len(reviewedHash) != 27){
|
|
reviewedHashHex := encoding.EncodeBytesToHexString(reviewedHash)
|
|
return false, errors.New("ReadReview returning invalid length reviewedHash for Attribute review: " + reviewedHashHex)
|
|
}
|
|
|
|
reviewedAttributeHash := [27]byte(reviewedHash)
|
|
|
|
anyExist, attributeProfileHashesList, err := badgerDatabase.GetAttributeProfilesList(reviewedAttributeHash)
|
|
if (err != nil) { return false, err }
|
|
if (anyExist == false){
|
|
return false, nil
|
|
}
|
|
|
|
for _, profileHash := range attributeProfileHashesList{
|
|
|
|
statusIsKnown, isFunded, _, _, err := verifiedFundedStatus.GetVerifiedMateProfileIsFundedStatus(profileHash)
|
|
if (err != nil) { return false, err }
|
|
if (statusIsKnown == true && isFunded == true){
|
|
return true, nil
|
|
}
|
|
}
|
|
|
|
return false, nil
|
|
}
|
|
|
|
anyAttributeProfileIsFunded, err := checkIfAnyAttributeProfileIsFunded()
|
|
if (err != nil) { return nil, err }
|
|
if (anyAttributeProfileIsFunded == false){
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
reviewsListForResponse = append(reviewsListForResponse, reviewBytes)
|
|
}
|
|
|
|
return reviewsListForResponse, nil
|
|
}
|
|
|
|
reviewsListForResponse, err := getReviewsListForResponse()
|
|
if (err != nil) { return nil, err }
|
|
|
|
responseBytes, err := serverResponse.CreateServerResponse_GetReviews(myHostPublicIdentityKey, myHostPrivateIdentityKey, connectionKey, requestIdentifier, reviewsListForResponse)
|
|
if (err != nil) { return nil, err }
|
|
|
|
return responseBytes, nil
|
|
}
|
|
if (requestType == "GetIdentityReportsInfo"){
|
|
|
|
acceptableVersionsList, identityTypeToRetrieve, requestRangeStart, requestRangeEnd, requestedReportedIdentityHashesList, err := serverRequest.ReadDecryptedServerRequest_GetIdentityReportsInfo(decryptedRequestBytes)
|
|
if (err != nil){
|
|
return invalidRequestResponse, nil
|
|
}
|
|
|
|
getReportsInfoMap := func()(map[[30]byte][]byte, error){
|
|
|
|
hostModeEnabled, hostingAny, myIdentityRangeStart, myIdentityRangeEnd, err := myRanges.GetMyIdentitiesToHostRange(identityTypeToRetrieve)
|
|
if (err != nil) { return nil, err }
|
|
if (hostModeEnabled == false){
|
|
// We must have turned off host mode recently
|
|
reportsInfoMap := make(map[[30]byte][]byte)
|
|
return reportsInfoMap, nil
|
|
}
|
|
if (hostingAny == false){
|
|
reportsInfoMap := make(map[[30]byte][]byte)
|
|
return reportsInfoMap, nil
|
|
}
|
|
|
|
// We include identity, profile and attribute reports
|
|
|
|
relevantReportHashesList := make([][30]byte, 0)
|
|
|
|
allReportedIdentityHashesList, err := badgerDatabase.GetAllReportedIdentityHashes()
|
|
if (err != nil) { return nil, err }
|
|
|
|
for _, identityHash := range allReportedIdentityHashesList{
|
|
|
|
anyExist, reportHashesList, err := badgerDatabase.GetIdentityReportsList(identityHash)
|
|
if (err != nil) { return nil, err }
|
|
if (anyExist == true){
|
|
relevantReportHashesList = append(relevantReportHashesList, reportHashesList...)
|
|
}
|
|
}
|
|
|
|
allReportedProfileHashesList, err := badgerDatabase.GetAllReportedProfileHashes()
|
|
if (err != nil) { return nil, err }
|
|
|
|
for _, profileHash := range allReportedProfileHashesList{
|
|
|
|
anyExist, reportHashesList, err := badgerDatabase.GetProfileReportsList(profileHash)
|
|
if (err != nil) { return nil, err }
|
|
if (anyExist == true){
|
|
relevantReportHashesList = append(relevantReportHashesList, reportHashesList...)
|
|
}
|
|
}
|
|
|
|
allReportedAttributeHashesList, err := badgerDatabase.GetAllReportedProfileAttributeHashes()
|
|
if (err != nil) { return nil, err }
|
|
|
|
for _, attributeHash := range allReportedAttributeHashesList{
|
|
|
|
anyExist, reportHashesList, err := badgerDatabase.GetProfileAttributeReportsList(attributeHash)
|
|
if (err != nil) { return nil, err }
|
|
if (anyExist == true){
|
|
relevantReportHashesList = append(relevantReportHashesList, reportHashesList...)
|
|
}
|
|
}
|
|
|
|
// Map Structure: Report Hash -> Reported Hash
|
|
reportsInfoMap := make(map[[30]byte][]byte)
|
|
|
|
for _, reportHash := range relevantReportHashesList{
|
|
|
|
statusIsKnown, reportIsFunded, _, _, err := verifiedFundedStatus.GetVerifiedReportIsFundedStatus(reportHash)
|
|
if (err != nil) { return nil, err }
|
|
if (statusIsKnown == false || reportIsFunded == false){
|
|
continue
|
|
}
|
|
|
|
reportExists, reportBytes, err := badgerDatabase.GetReport(reportHash)
|
|
if (err != nil) { return nil, err }
|
|
if (reportExists == false){
|
|
continue
|
|
}
|
|
|
|
ableToRead, currentReportHash, reportVersion, reportNetworkType, _, reportType, reportedHash, _, err := readReports.ReadReportAndHash(false, reportBytes)
|
|
if (err != nil) { return nil, err }
|
|
if (ableToRead == false){
|
|
return nil, errors.New("Database corrupt: Contains invalid report.")
|
|
}
|
|
if (reportHash != currentReportHash){
|
|
return nil, errors.New("Database corrupt: Report entry key does not match report hash")
|
|
}
|
|
isAcceptableVersion := slices.Contains(acceptableVersionsList, reportVersion)
|
|
if (isAcceptableVersion == false){
|
|
// This report is of a version that the requestor cannot accept
|
|
// We must be running a different version of Seekia than them.
|
|
continue
|
|
}
|
|
if (reportNetworkType != networkType){
|
|
// Report belongs to a different networkType
|
|
continue
|
|
}
|
|
|
|
//Outputs:
|
|
// -bool: Report is malicious
|
|
// -bool: Metadata exists
|
|
// -[16]byte: Reported identity hash
|
|
// -error
|
|
getReportedIdentityHash := func()(bool, bool, [16]byte, error){
|
|
|
|
if (reportType == "Identity"){
|
|
|
|
if (len(reportedHash) != 16){
|
|
reportedHashHex := encoding.EncodeBytesToHexString(reportedHash)
|
|
return false, false, [16]byte{}, errors.New("ReadReport returning invalid length reportedHash for Identity report: " + reportedHashHex)
|
|
}
|
|
|
|
reportedIdentityHash := [16]byte(reportedHash)
|
|
|
|
return false, true, reportedIdentityHash, nil
|
|
}
|
|
if (reportType == "Profile"){
|
|
|
|
if (len(reportedHash) != 28){
|
|
reportedHashHex := encoding.EncodeBytesToHexString(reportedHash)
|
|
return false, false, [16]byte{}, errors.New("ReadReport returning invalid length reportedHash for Profile report: " + reportedHashHex)
|
|
}
|
|
|
|
reportedProfileHash := [28]byte(reportedHash)
|
|
|
|
metadataExists, _, profileNetworkType, profileAuthor, _, _, _, _, err := contentMetadata.GetProfileMetadata(reportedProfileHash)
|
|
if (err != nil) { return false, false, [16]byte{}, err }
|
|
if (metadataExists == false){
|
|
return false, false, [16]byte{}, nil
|
|
}
|
|
if (profileNetworkType != reportNetworkType){
|
|
// Report author must be malicious
|
|
// Report is reporting a profile on a different network
|
|
return true, false, [16]byte{}, nil
|
|
}
|
|
|
|
return false, true, profileAuthor, nil
|
|
}
|
|
if (reportType == "Attribute"){
|
|
|
|
if (len(reportedHash) != 27){
|
|
reportedHashHex := encoding.EncodeBytesToHexString(reportedHash)
|
|
return false, false, [16]byte{}, errors.New("ReadReport returning invalid length reportedHash for Attribute report: " + reportedHashHex)
|
|
}
|
|
|
|
reportedAttributeHash := [27]byte(reportedHash)
|
|
|
|
metadataExists, _, authorIdentityHash, attributeNetworkType, _, err := profileStorage.GetProfileAttributeMetadata(reportedAttributeHash)
|
|
if (err != nil){ return false, false, [16]byte{}, err }
|
|
if (metadataExists == false){
|
|
return false, false, [16]byte{}, nil
|
|
}
|
|
if (attributeNetworkType != networkType){
|
|
// Report author must be malicious
|
|
// Report is reporting an attribute on a different network
|
|
return true, false, [16]byte{}, nil
|
|
}
|
|
|
|
return false, true, authorIdentityHash, nil
|
|
}
|
|
|
|
return false, false, [16]byte{}, errors.New("getReportedIdentityHash reached with invalid reportType: " + reportType)
|
|
}
|
|
|
|
reportIsMalicious, metadataExists, reportedIdentityHash, err := getReportedIdentityHash()
|
|
if (err != nil) { return nil, err }
|
|
if (reportIsMalicious == true){
|
|
// We will not serve malicious reports
|
|
continue
|
|
}
|
|
if (metadataExists == false){
|
|
// We cannot serve reports whose reported author we do not know.
|
|
continue
|
|
}
|
|
|
|
reportedIdentityType, err := identity.GetIdentityTypeFromIdentityHash(reportedIdentityHash)
|
|
if (err != nil){ return nil, err }
|
|
if (reportedIdentityType != identityTypeToRetrieve){
|
|
continue
|
|
}
|
|
|
|
if (len(requestedReportedIdentityHashesList) != 0){
|
|
|
|
// We will find report hashes from requested reportedHashes list
|
|
|
|
isWithinList := slices.Contains(requestedReportedIdentityHashesList, reportedIdentityHash)
|
|
if (isWithinList == false){
|
|
continue
|
|
}
|
|
} else {
|
|
|
|
// We make sure reported identity is within requested range
|
|
|
|
identityIsInRequestRange, err := byteRange.CheckIfIdentityHashIsWithinRange(requestRangeStart, requestRangeEnd, reportedIdentityHash)
|
|
if (err != nil) { return nil, err }
|
|
if (identityIsInRequestRange == false){
|
|
continue
|
|
}
|
|
}
|
|
|
|
// We make sure identity is within our range
|
|
|
|
identityIsInMyRange, err := byteRange.CheckIfIdentityHashIsWithinRange(myIdentityRangeStart, myIdentityRangeEnd, reportedIdentityHash)
|
|
if (err != nil) { return nil, err }
|
|
if (identityIsInMyRange == false){
|
|
continue
|
|
}
|
|
|
|
// We make sure that the profile/identity being reported is funded
|
|
|
|
if (reportedIdentityType == "Moderator"){
|
|
|
|
statusIsKnown, _, scoreIsSufficient, _, _, err := moderatorScores.GetModeratorIdentityScore(reportedIdentityHash)
|
|
if (err != nil) { return nil, err }
|
|
if (statusIsKnown == false || scoreIsSufficient == false){
|
|
continue
|
|
}
|
|
|
|
} else {
|
|
|
|
// reviewedIdentityType == "Mate" or "Host"
|
|
|
|
statusIsKnown, isFunded, _, _, err := verifiedFundedStatus.GetVerifiedIdentityIsFundedStatus(reportedIdentityHash, networkType)
|
|
if (err != nil) { return nil, err }
|
|
if (statusIsKnown == false || isFunded == false){
|
|
continue
|
|
}
|
|
}
|
|
|
|
if (reportedIdentityType == "Mate" && reportType == "Profile"){
|
|
|
|
// We make sure profile is funded
|
|
|
|
if (len(reportedHash) != 28){
|
|
reportedHashHex := encoding.EncodeBytesToHexString(reportedHash)
|
|
return nil, errors.New("ReadReport returning invalid length reportedHash for Profile report: " + reportedHashHex)
|
|
}
|
|
|
|
reportedProfileHash := [28]byte(reportedHash)
|
|
|
|
statusIsKnown, isFunded, _, _, err := verifiedFundedStatus.GetVerifiedMateProfileIsFundedStatus(reportedProfileHash)
|
|
if (err != nil) { return nil, err }
|
|
if (statusIsKnown == false || isFunded == false){
|
|
continue
|
|
}
|
|
|
|
} else if (reportedIdentityType == "Mate" && reportType == "Attribute"){
|
|
|
|
// We make sure at least 1 profile with this attribute is funded
|
|
|
|
checkIfAnyAttributeProfileIsFunded := func()(bool, error){
|
|
|
|
if (len(reportedHash) != 27){
|
|
reportedHashHex := encoding.EncodeBytesToHexString(reportedHash)
|
|
return false, errors.New("ReadReport returning invalid length reportedHash for Attribute report: " + reportedHashHex)
|
|
}
|
|
|
|
reportedAttributeHash := [27]byte(reportedHash)
|
|
|
|
anyExist, attributeProfileHashesList, err := badgerDatabase.GetAttributeProfilesList(reportedAttributeHash)
|
|
if (err != nil) { return false, err }
|
|
if (anyExist == false){
|
|
return false, nil
|
|
}
|
|
|
|
for _, profileHash := range attributeProfileHashesList{
|
|
|
|
statusIsKnown, isFunded, _, _, err := verifiedFundedStatus.GetVerifiedMateProfileIsFundedStatus(profileHash)
|
|
if (err != nil) { return false, err }
|
|
if (statusIsKnown == true && isFunded == true){
|
|
return true, nil
|
|
}
|
|
}
|
|
|
|
return false, nil
|
|
}
|
|
|
|
anyAttributeProfileIsFunded, err := checkIfAnyAttributeProfileIsFunded()
|
|
if (err != nil) { return nil, err }
|
|
if (anyAttributeProfileIsFunded == false){
|
|
continue
|
|
}
|
|
}
|
|
|
|
reportsInfoMap[reportHash] = reportedHash
|
|
}
|
|
|
|
return reportsInfoMap, nil
|
|
}
|
|
|
|
reportsInfoMap, err := getReportsInfoMap()
|
|
if (err != nil) { return nil, err }
|
|
|
|
responseBytes, err := serverResponse.CreateServerResponse_GetIdentityReportsInfo(myHostPublicIdentityKey, myHostPrivateIdentityKey, connectionKey, requestIdentifier, reportsInfoMap)
|
|
if (err != nil) { return nil, err }
|
|
|
|
return responseBytes, nil
|
|
}
|
|
if (requestType == "GetMessageReportsInfo"){
|
|
|
|
acceptableVersionsList, requestRangeStart, requestRangeEnd, requestedReportedMessageHashesList, err := serverRequest.ReadDecryptedServerRequest_GetMessageReportsInfo(decryptedRequestBytes)
|
|
if (err != nil){
|
|
return invalidRequestResponse, nil
|
|
}
|
|
|
|
getReportsInfoMap := func()(map[[30]byte][26]byte, error){
|
|
|
|
hostModeEnabled, hostingAnyInboxes, myInboxRangeStart, myInboxRangeEnd, err := myRanges.GetMyInboxesToHostRange()
|
|
if (err != nil) { return nil, err }
|
|
if (hostModeEnabled == false){
|
|
// We must have disabled host mode recently
|
|
reportsInfoMap := make(map[[30]byte][26]byte)
|
|
return reportsInfoMap, nil
|
|
}
|
|
if (hostingAnyInboxes == false){
|
|
// We are not hosting any messages/ message reports
|
|
reportsInfoMap := make(map[[30]byte][26]byte)
|
|
return reportsInfoMap, nil
|
|
}
|
|
|
|
getRelevantMessageHashesList := func()([][26]byte, error){
|
|
|
|
if (len(requestedReportedMessageHashesList) != 0){
|
|
|
|
// We will get reports from requested message hashes list
|
|
|
|
return requestedReportedMessageHashesList, nil
|
|
}
|
|
|
|
allReportedMessageHashesList, err := badgerDatabase.GetAllReportedMessageHashes()
|
|
if (err != nil) { return nil, err }
|
|
|
|
return allReportedMessageHashesList, nil
|
|
}
|
|
|
|
relevantMessageHashesList, err := getRelevantMessageHashesList()
|
|
if (err != nil) { return nil, err }
|
|
|
|
relevantReportHashesList := make([][30]byte, 0)
|
|
|
|
for _, messageHash := range relevantMessageHashesList{
|
|
|
|
anyExist, reportHashesList, err := badgerDatabase.GetMessageReportsList(messageHash)
|
|
if (err != nil) { return nil, err }
|
|
if (anyExist == true){
|
|
relevantReportHashesList = append(relevantReportHashesList, reportHashesList...)
|
|
}
|
|
}
|
|
|
|
// Map Structure: Report Hash -> Reported Message Hash
|
|
reportsInfoMap := make(map[[30]byte][26]byte)
|
|
|
|
for _, reportHash := range relevantReportHashesList{
|
|
|
|
statusIsKnown, reportIsFunded, _, _, err := verifiedFundedStatus.GetVerifiedReportIsFundedStatus(reportHash)
|
|
if (err != nil) { return nil, err }
|
|
if (statusIsKnown == false || reportIsFunded == false){
|
|
continue
|
|
}
|
|
|
|
reportExists, reportBytes, err := badgerDatabase.GetReport(reportHash)
|
|
if (err != nil) { return nil, err }
|
|
if (reportExists == false){
|
|
continue
|
|
}
|
|
|
|
ableToRead, currentReportHash, reportVersion, reportNetworkType, _, reportType, reportedHash, _, err := readReports.ReadReportAndHash(false, reportBytes)
|
|
if (err != nil) { return nil, err }
|
|
if (ableToRead == false){
|
|
return nil, errors.New("Database corrupt: Contains invalid report.")
|
|
}
|
|
if (reportHash != currentReportHash){
|
|
return nil, errors.New("Database corrupt: Report entry key does not match report hash")
|
|
}
|
|
|
|
if (reportType != "Message"){
|
|
return nil, errors.New("Database corrupt: Message reports list contains non-message report")
|
|
}
|
|
|
|
if (len(reportedHash) != 26){
|
|
reportedHashHex := encoding.EncodeBytesToHexString(reportedHash)
|
|
return nil, errors.New("ReadReport returning invalid length reportedHash for Message report: " + reportedHashHex)
|
|
}
|
|
|
|
reportedMessageHash := [26]byte(reportedHash)
|
|
|
|
isAcceptableVersion := slices.Contains(acceptableVersionsList, reportVersion)
|
|
if (isAcceptableVersion == false){
|
|
// This report is of a version that the requestor cannot accept
|
|
// We must be running a different version of Seekia than them.
|
|
continue
|
|
}
|
|
if (reportNetworkType != networkType){
|
|
// Report belongs to a different networkType
|
|
continue
|
|
}
|
|
|
|
metadataExists, _, messageNetworkType, _, messageInbox, _, err := contentMetadata.GetMessageMetadata(reportedMessageHash)
|
|
if (err != nil) { return nil, err }
|
|
if (metadataExists == false){
|
|
// We cannot seed reports for messages whose metadata we do not know
|
|
continue
|
|
}
|
|
if (messageNetworkType != networkType){
|
|
// Report author must be malicious
|
|
// They have created a report for a message belonging to a different networkType
|
|
continue
|
|
}
|
|
|
|
isWithinMyRange, err := byteRange.CheckIfInboxIsWithinRange(myInboxRangeStart, myInboxRangeEnd, messageInbox)
|
|
if (err != nil) { return nil, err }
|
|
if (isWithinMyRange == false){
|
|
continue
|
|
}
|
|
|
|
// We reduce the requested reports based on requested inbox range
|
|
|
|
isWithinRequestRange, err := byteRange.CheckIfInboxIsWithinRange(requestRangeStart, requestRangeEnd, messageInbox)
|
|
if (err != nil) { return nil, err }
|
|
if (isWithinRequestRange == false){
|
|
continue
|
|
}
|
|
|
|
// We make sure message is funded
|
|
|
|
statusIsKnown, messageIsFunded, _, _, err := verifiedFundedStatus.GetVerifiedMessageIsFundedStatus(reportedMessageHash)
|
|
if (err != nil) { return nil, err }
|
|
if (statusIsKnown == false || messageIsFunded == false){
|
|
continue
|
|
}
|
|
|
|
reportsInfoMap[reportHash] = reportedMessageHash
|
|
}
|
|
|
|
return reportsInfoMap, nil
|
|
}
|
|
|
|
reportsInfoMap, err := getReportsInfoMap()
|
|
if (err != nil) { return nil, err }
|
|
|
|
responseBytes, err := serverResponse.CreateServerResponse_GetMessageReportsInfo(myHostPublicIdentityKey, myHostPrivateIdentityKey, connectionKey, requestIdentifier, reportsInfoMap)
|
|
if (err != nil) { return nil, err }
|
|
|
|
return responseBytes, nil
|
|
}
|
|
if (requestType == "GetReports"){
|
|
|
|
requestedReportHashesList, err := serverRequest.ReadDecryptedServerRequest_GetReports(decryptedRequestBytes)
|
|
if (err != nil) { return nil, err }
|
|
|
|
getReportsListForResponse := func()([][]byte, error){
|
|
|
|
// We will reduce report list to only include reports within our hosted range
|
|
// This is done to prevent fingerprinting
|
|
|
|
// We also make sure reported identities/profiles/messages are funded
|
|
|
|
reportsListForResponse := make([][]byte, 0)
|
|
|
|
for _, reportHash := range requestedReportHashesList{
|
|
|
|
reportExists, reportBytes, err := badgerDatabase.GetReport(reportHash)
|
|
if (err != nil) { return nil, err }
|
|
if (reportExists == false){
|
|
continue
|
|
}
|
|
|
|
ableToRead, currentReportHash, _, reportNetworkType, _, reportType, reportedHash, _, err := readReports.ReadReportAndHash(false, reportBytes)
|
|
if (err != nil) { return nil, err }
|
|
if (ableToRead == false){
|
|
return nil, errors.New("Database corrupt: Contains invalid report.")
|
|
}
|
|
if (reportHash != currentReportHash){
|
|
return nil, errors.New("Database corrupt: Contains report with mismatched reportHash entry key")
|
|
}
|
|
if (reportNetworkType != networkType){
|
|
// Requestor must be malicious
|
|
// They should only request reports which we offered them
|
|
// We will only have offered them reports on the current networkType
|
|
continue
|
|
}
|
|
|
|
if (reportType == "Message"){
|
|
|
|
if (len(reportedHash) != 26){
|
|
reportedHashHex := encoding.EncodeBytesToHexString(reportedHash)
|
|
return nil, errors.New("ReadReport returning invalid length reportedHash for Message report: " + reportedHashHex)
|
|
}
|
|
|
|
reportedMessageHash := [26]byte(reportedHash)
|
|
|
|
metadataExists, _, messageNetworkType, _, messageInbox, _, err := contentMetadata.GetMessageMetadata(reportedMessageHash)
|
|
if (err != nil){ return nil, err }
|
|
if (metadataExists == false){
|
|
// We cannot host reports for messages whose metadata we do not have.
|
|
continue
|
|
}
|
|
if (messageNetworkType != networkType){
|
|
// This should not happen because we would have already checked for this before serving report info to requestor
|
|
// Requestor must be maliciously requesting reports we never offered them
|
|
continue
|
|
}
|
|
|
|
hostModeEnabled, isWithinMyRange, err := myRanges.CheckIfMessageInboxIsWithinMyHostedRange(messageInbox)
|
|
if (err != nil) { return nil, err }
|
|
if (hostModeEnabled == false){
|
|
// Host mode must have been disabled after earlier check. Return empty list.
|
|
emptyList := make([][]byte, 0)
|
|
return emptyList, nil
|
|
}
|
|
if (isWithinMyRange == false){
|
|
continue
|
|
}
|
|
|
|
// We make sure message is funded
|
|
|
|
statusIsKnown, messageIsFunded, _, _, err := verifiedFundedStatus.GetVerifiedMessageIsFundedStatus(reportedMessageHash)
|
|
if (err != nil) { return nil, err }
|
|
if (statusIsKnown == false || messageIsFunded == false){
|
|
continue
|
|
}
|
|
|
|
} else {
|
|
|
|
// reportType == "Identity" or "Profile" or "Attribute"
|
|
|
|
//Outputs:
|
|
// -bool: Report is malicious
|
|
// -bool: Reported identity hash found
|
|
// -[16]byte: Reported identity hash
|
|
// -error
|
|
getReportedIdentityHash := func()(bool, bool, [16]byte, error){
|
|
|
|
if (reportType == "Identity"){
|
|
|
|
if (len(reportedHash) != 16){
|
|
reportedHashHex := encoding.EncodeBytesToHexString(reportedHash)
|
|
return false, false, [16]byte{}, errors.New("ReadReport returning invalid length reportedHash for Identity report: " + reportedHashHex)
|
|
}
|
|
|
|
reportedIdentityHash := [16]byte(reportedHash)
|
|
|
|
return false, true, reportedIdentityHash, nil
|
|
}
|
|
if (reportType == "Profile"){
|
|
|
|
if (len(reportedHash) != 28){
|
|
reportedHashHex := encoding.EncodeBytesToHexString(reportedHash)
|
|
return false, false, [16]byte{}, errors.New("ReadReport returning invalid length reportedHash for Profile report: " + reportedHashHex)
|
|
}
|
|
|
|
reportedProfileHash := [28]byte(reportedHash)
|
|
|
|
metadataExists, _, profileNetworkType, profileAuthor, _, _, _, _, err := contentMetadata.GetProfileMetadata(reportedProfileHash)
|
|
if (err != nil) { return false, false, [16]byte{}, err }
|
|
if (metadataExists == false){
|
|
return false, false, [16]byte{}, nil
|
|
}
|
|
if (profileNetworkType != networkType){
|
|
return true, false, [16]byte{}, nil
|
|
}
|
|
|
|
return false, true, profileAuthor, nil
|
|
}
|
|
if (reportType == "Attribute"){
|
|
|
|
if (len(reportedHash) != 27){
|
|
reportedHashHex := encoding.EncodeBytesToHexString(reportedHash)
|
|
return false, false, [16]byte{}, errors.New("ReadReport returning invalid length reportedHash for Attribute report: " + reportedHashHex)
|
|
}
|
|
|
|
reportedAttributeHash := [27]byte(reportedHash)
|
|
|
|
metadataExists, _, authorIdentityHash, attributeNetworkType, _, err := profileStorage.GetProfileAttributeMetadata(reportedAttributeHash)
|
|
if (err != nil){ return false, false, [16]byte{}, err }
|
|
if (metadataExists == false){
|
|
return false, false, [16]byte{}, nil
|
|
}
|
|
if (attributeNetworkType != networkType){
|
|
return true, false, [16]byte{}, nil
|
|
}
|
|
|
|
return false, true, authorIdentityHash, nil
|
|
}
|
|
|
|
return false, false, [16]byte{}, errors.New("ReadReport returning invalid reportType: " + reportType)
|
|
}
|
|
|
|
reportIsMalicious, metadataExists, reportedIdentityHash, err := getReportedIdentityHash()
|
|
if (err != nil) { return nil, err }
|
|
if (reportIsMalicious == true){
|
|
// The requestor must be malicious, because we should have already checked for this condition
|
|
// before serving this report hash in our Get...ReportsInfo responses.
|
|
continue
|
|
}
|
|
if (metadataExists == false){
|
|
// We cannot seed a report whose reported identity hash we do not know
|
|
continue
|
|
}
|
|
|
|
// We make sure identity is within our hosted range
|
|
|
|
hostModeEnabled, isInMyRange, err := myRanges.CheckIfIdentityHashIsWithinMyHostedRange(reportedIdentityHash)
|
|
if (err != nil) { return nil, err }
|
|
if (hostModeEnabled == false){
|
|
// Host mode must have been disabled after earlier check. Return empty list.
|
|
emptyList := make([][]byte, 0)
|
|
return emptyList, nil
|
|
}
|
|
|
|
if (isInMyRange == false){
|
|
continue
|
|
}
|
|
|
|
// We make sure identity is funded
|
|
|
|
reportedIdentityType, err := identity.GetIdentityTypeFromIdentityHash(reportedIdentityHash)
|
|
if (err != nil){ return nil, err }
|
|
|
|
if (reportedIdentityType == "Moderator"){
|
|
|
|
statusIsKnown, _, scoreIsSufficient, _, _, err := moderatorScores.GetModeratorIdentityScore(reportedIdentityHash)
|
|
if (err != nil) { return nil, err }
|
|
if (statusIsKnown == false || scoreIsSufficient == false){
|
|
continue
|
|
}
|
|
|
|
} else {
|
|
|
|
// reportedIdentityType == "Mate" or "Host"
|
|
|
|
statusIsKnown, isFunded, _, _, err := verifiedFundedStatus.GetVerifiedIdentityIsFundedStatus(reportedIdentityHash, networkType)
|
|
if (err != nil) { return nil, err }
|
|
if (statusIsKnown == false || isFunded == false){
|
|
continue
|
|
}
|
|
}
|
|
|
|
if (reportedIdentityType == "Mate" && reportType == "Profile"){
|
|
|
|
// We make sure profile is funded
|
|
|
|
if (len(reportedHash) != 28){
|
|
reportedHashHex := encoding.EncodeBytesToHexString(reportedHash)
|
|
return nil, errors.New("ReadReport returning invalid length reportedHash for Profile report: " + reportedHashHex)
|
|
}
|
|
|
|
reportedProfileHash := [28]byte(reportedHash)
|
|
|
|
statusIsKnown, isFunded, _, _, err := verifiedFundedStatus.GetVerifiedMateProfileIsFundedStatus(reportedProfileHash)
|
|
if (err != nil) { return nil, err }
|
|
if (statusIsKnown == false || isFunded == false){
|
|
continue
|
|
}
|
|
} else if (reportedIdentityType == "Mate" && reportType == "Attribute"){
|
|
|
|
// We make sure at least 1 profile with this attribute is funded
|
|
|
|
if (len(reportedHash) != 27){
|
|
reportedHashHex := encoding.EncodeBytesToHexString(reportedHash)
|
|
return nil, errors.New("ReadReport returning invalid length reportedHash for Attribute report: " + reportedHashHex)
|
|
}
|
|
|
|
reportedAttributeHash := [27]byte(reportedHash)
|
|
|
|
checkIfAnyAttributeProfileIsFunded := func()(bool, error){
|
|
|
|
anyExist, attributeProfileHashesList, err := badgerDatabase.GetAttributeProfilesList(reportedAttributeHash)
|
|
if (err != nil) { return false, err }
|
|
if (anyExist == false){
|
|
return false, nil
|
|
}
|
|
|
|
for _, profileHash := range attributeProfileHashesList{
|
|
|
|
statusIsKnown, isFunded, _, _, err := verifiedFundedStatus.GetVerifiedMateProfileIsFundedStatus(profileHash)
|
|
if (err != nil) { return false, err }
|
|
if (statusIsKnown == true && isFunded == true){
|
|
return true, nil
|
|
}
|
|
}
|
|
|
|
return false, nil
|
|
}
|
|
|
|
anyAttributeProfileIsFunded, err := checkIfAnyAttributeProfileIsFunded()
|
|
if (err != nil) { return nil, err }
|
|
if (anyAttributeProfileIsFunded == false){
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
reportsListForResponse = append(reportsListForResponse, reportBytes)
|
|
}
|
|
|
|
return reportsListForResponse, nil
|
|
}
|
|
|
|
reportsListForResponse, err := getReportsListForResponse()
|
|
if (err != nil) { return nil, err }
|
|
|
|
responseBytes, err := serverResponse.CreateServerResponse_GetReports(myHostPublicIdentityKey, myHostPrivateIdentityKey, connectionKey, requestIdentifier, reportsListForResponse)
|
|
if (err != nil) { return nil, err }
|
|
|
|
return responseBytes, nil
|
|
}
|
|
if (requestType == "GetViewableStatuses"){
|
|
|
|
requestedIdentityHashesList, requestedProfileHashesList, err := serverRequest.ReadDecryptedServerRequest_GetViewableStatuses(decryptedRequestBytes)
|
|
if (err != nil){
|
|
return invalidRequestResponse, nil
|
|
}
|
|
|
|
getIdentityHashStatusesMap := func()(map[[16]byte]bool, error){
|
|
|
|
// Map Structure: Identity Hash -> Is Viewable status
|
|
identityHashStatusesMap := make(map[[16]byte]bool)
|
|
|
|
for _, userIdentityHash := range requestedIdentityHashesList{
|
|
|
|
hostModeEnabled, isWithinMyRange, err := myRanges.CheckIfIdentityHashIsWithinMyHostedRange(userIdentityHash)
|
|
if (err != nil) { return nil, err }
|
|
if (hostModeEnabled == false){
|
|
// Host mode has been disabled. We return empty response.
|
|
emptyMap := make(map[[16]byte]bool)
|
|
return emptyMap, nil
|
|
}
|
|
if (isWithinMyRange == false){
|
|
continue
|
|
}
|
|
|
|
// We make sure identity is funded
|
|
|
|
userIdentityType, err := identity.GetIdentityTypeFromIdentityHash(userIdentityHash)
|
|
if (err != nil) { return nil, err }
|
|
|
|
if (userIdentityType == "Moderator"){
|
|
|
|
statusIsKnown, _, scoreIsSufficient, _, _, err := moderatorScores.GetModeratorIdentityScore(userIdentityHash)
|
|
if (err != nil) { return nil, err }
|
|
if (statusIsKnown == false || scoreIsSufficient == false){
|
|
continue
|
|
}
|
|
|
|
} else {
|
|
|
|
// userIdentityType == "Mate" or "Host"
|
|
|
|
statusIsKnown, isFunded, _, _, err := verifiedFundedStatus.GetVerifiedIdentityIsFundedStatus(userIdentityHash, networkType)
|
|
if (err != nil) { return nil, err }
|
|
if (statusIsKnown == false || isFunded == false){
|
|
continue
|
|
}
|
|
}
|
|
|
|
downloadingRequiredReviews, parametersExist, stickyStatusEstablished, identityIsViewableStatus, err := verifiedStickyStatus.GetVerifiedIdentityIsViewableStickyStatus(userIdentityHash, networkType)
|
|
if (err != nil) { return nil, err }
|
|
if (downloadingRequiredReviews == false){
|
|
continue
|
|
}
|
|
if (parametersExist == false){
|
|
// Host needs to download required moderation parameters to know sticky consensuses.
|
|
// We skip identities.
|
|
break
|
|
}
|
|
if (stickyStatusEstablished == false){
|
|
continue
|
|
}
|
|
|
|
identityHashStatusesMap[userIdentityHash] = identityIsViewableStatus
|
|
}
|
|
|
|
return identityHashStatusesMap, nil
|
|
}
|
|
|
|
identityHashStatusesMap, err := getIdentityHashStatusesMap()
|
|
if (err != nil) { return nil, err }
|
|
|
|
getProfileHashStatusesMap := func()(map[[28]byte]bool, error){
|
|
|
|
// Map Structure: Profile Hash -> Is Viewable status
|
|
profileHashStatusesMap := make(map[[28]byte]bool)
|
|
|
|
for _, profileHash := range requestedProfileHashesList{
|
|
|
|
profileIsDisabled, profileMetadataIsKnown, profileNetworkType, profileAuthor, downloadingRequiredReviews, parametersFound, stickyStatusEstablished, profileIsViewableStatus, err := verifiedStickyStatus.GetVerifiedProfileIsViewableStickyStatus(profileHash)
|
|
if (err != nil) { return nil, err }
|
|
if (profileMetadataIsKnown == false){
|
|
// We don't know profile author, so we cannot check if author is banned, or if profile is banned.
|
|
// We don't know sticky status. We skip profile.
|
|
continue
|
|
}
|
|
if (profileNetworkType != networkType){
|
|
// Requestor must be malicious
|
|
// They should only request viewable statuses for profiles on our networkType
|
|
continue
|
|
}
|
|
|
|
if (profileIsDisabled == false){
|
|
if (downloadingRequiredReviews == false){
|
|
continue
|
|
}
|
|
if (parametersFound == false){
|
|
// Host needs to download required network parameters to host sticky consensuses.
|
|
// We skip all profiles.
|
|
break
|
|
}
|
|
if (stickyStatusEstablished == false){
|
|
continue
|
|
}
|
|
}
|
|
|
|
hostModeEnabled, isWithinMyRange, err := myRanges.CheckIfIdentityHashIsWithinMyHostedRange(profileAuthor)
|
|
if (err != nil) { return nil, err }
|
|
if (hostModeEnabled == false){
|
|
// Host mode has been disabled. Return empty response.
|
|
emptyMap := make(map[[28]byte]bool)
|
|
return emptyMap, nil
|
|
}
|
|
if (isWithinMyRange == false){
|
|
continue
|
|
}
|
|
|
|
// We make sure identity is funded
|
|
|
|
profileIdentityType, err := identity.GetIdentityTypeFromIdentityHash(profileAuthor)
|
|
if (err != nil){ return nil, err }
|
|
|
|
if (profileIdentityType == "Moderator"){
|
|
|
|
statusIsKnown, _, scoreIsSufficient, _, _, err := moderatorScores.GetModeratorIdentityScore(profileAuthor)
|
|
if (err != nil) { return nil, err }
|
|
if (statusIsKnown == false || scoreIsSufficient == false){
|
|
continue
|
|
}
|
|
|
|
} else {
|
|
|
|
// profileIdentityType == "Mate" or "Host"
|
|
|
|
statusIsKnown, isFunded, _, _, err := verifiedFundedStatus.GetVerifiedIdentityIsFundedStatus(profileAuthor, networkType)
|
|
if (err != nil) { return nil, err }
|
|
if (statusIsKnown == false || isFunded == false){
|
|
continue
|
|
}
|
|
}
|
|
|
|
// If profile is Mate, we make sure it is funded
|
|
|
|
if (profileIdentityType == "Mate"){
|
|
|
|
statusIsKnown, isFunded, _, _, err := verifiedFundedStatus.GetVerifiedMateProfileIsFundedStatus(profileHash)
|
|
if (err != nil) { return nil, err }
|
|
if (statusIsKnown == false || isFunded == false){
|
|
continue
|
|
}
|
|
}
|
|
|
|
if (profileIsDisabled == false && profileIsViewableStatus == false){
|
|
// Profile is unviewable
|
|
profileHashStatusesMap[profileHash] = false
|
|
continue
|
|
}
|
|
|
|
// Profile is viewable
|
|
// Now we check to make sure identity is not banned
|
|
|
|
downloadingRequiredReviews, parametersExist, stickyStatusEstablished, identityIsViewableStatus, err := verifiedStickyStatus.GetVerifiedIdentityIsViewableStickyStatus(profileAuthor, networkType)
|
|
if (err != nil) { return nil, err }
|
|
if (downloadingRequiredReviews == false){
|
|
continue
|
|
}
|
|
if (parametersExist == false){
|
|
// Host needs to download required moderation parameters to host sticky consensuses.
|
|
// We skip identity hashes for now.
|
|
break
|
|
}
|
|
|
|
if (stickyStatusEstablished == false){
|
|
continue
|
|
}
|
|
|
|
profileHashStatusesMap[profileHash] = identityIsViewableStatus
|
|
}
|
|
|
|
return profileHashStatusesMap, nil
|
|
}
|
|
|
|
profileHashStatusesMap, err := getProfileHashStatusesMap()
|
|
if (err != nil) { return nil, err }
|
|
|
|
responseBytes, err := serverResponse.CreateServerResponse_GetViewableStatuses(myHostPublicIdentityKey, myHostPrivateIdentityKey, connectionKey, requestIdentifier, identityHashStatusesMap, profileHashStatusesMap)
|
|
if (err != nil) { return nil, err }
|
|
|
|
return responseBytes, nil
|
|
}
|
|
if (requestType == "BroadcastContent"){
|
|
|
|
contentTypeToBroadcast, contentBytesList, err := serverRequest.ReadDecryptedServerRequest_BroadcastContent(decryptedRequestBytes)
|
|
if (err != nil){
|
|
return invalidRequestResponse, nil
|
|
}
|
|
|
|
// Map Structure: Content Hash -> We will accept and host
|
|
contentAcceptedInfoMap := make(map[string]bool)
|
|
|
|
// If host mode is disabled during this process, we will set this bool to true
|
|
// If true, we will return an response which has contentAccepted = "No" for all content hashes
|
|
hostModeDisabled := false
|
|
|
|
for _, contentBytes := range contentBytesList{
|
|
|
|
if (contentTypeToBroadcast == "Parameters"){
|
|
|
|
ableToRead, parametersHash, _, parametersNetworkType, _, _, _, _, err := readParameters.ReadParametersAndHash(false, contentBytes)
|
|
if (err != nil) { return nil, err }
|
|
if (ableToRead == false){
|
|
return nil, errors.New("ReadDecryptedServerRequest_BroadcastContent not verifying parameters are valid")
|
|
}
|
|
if (parametersNetworkType != networkType){
|
|
// Requestor must be malicious
|
|
// They should only broadcast content which belongs to our networkType.
|
|
contentAcceptedInfoMap[string(parametersHash[:])] = false
|
|
continue
|
|
}
|
|
|
|
//TODO: Check if we are hosting parameters
|
|
|
|
contentAcceptedInfoMap[string(parametersHash[:])] = true
|
|
|
|
_, _, err = parametersStorage.AddParameters(contentBytes)
|
|
if (err != nil) { return nil, err }
|
|
|
|
continue
|
|
}
|
|
if (contentTypeToBroadcast == "Message"){
|
|
|
|
ableToRead, messageHash, _, messageNetworkType, messageInbox, _, _, _, _, _, _, err := readMessages.ReadChatMessagePublicDataAndHash(false, contentBytes)
|
|
if (err != nil){
|
|
return nil, errors.New("ReadDecryptedServerRequest_BroadcastContent not verifying message is valid")
|
|
}
|
|
if (ableToRead == false){
|
|
return nil, errors.New("ReadDecryptedServerRequest_BroadcastContent not verifying message is valid")
|
|
}
|
|
if (messageNetworkType != networkType){
|
|
// Requestor must be malicious
|
|
// They should only broadcast content which belongs to our networkType.
|
|
contentAcceptedInfoMap[string(messageHash[:])] = false
|
|
continue
|
|
}
|
|
|
|
hostModeEnabled, isWithinMyRange, err := myRanges.CheckIfMessageInboxIsWithinMyHostedRange(messageInbox)
|
|
if (err != nil) { return nil, err }
|
|
if (hostModeEnabled == false){
|
|
hostModeDisabled = true
|
|
contentAcceptedInfoMap[string(messageHash[:])] = false
|
|
continue
|
|
}
|
|
|
|
contentAcceptedInfoMap[string(messageHash[:])] = isWithinMyRange
|
|
|
|
if (isWithinMyRange == true){
|
|
|
|
// We add message to database
|
|
|
|
messageIsWellFormed, err := chatMessageStorage.AddMessage(contentBytes)
|
|
if (err != nil) { return nil, err }
|
|
if (messageIsWellFormed == false){
|
|
return nil, errors.New("AddMessage not verifying message the same way ReadChatMessagePublicData is")
|
|
}
|
|
}
|
|
|
|
continue
|
|
}
|
|
if (contentTypeToBroadcast == "Profile"){
|
|
|
|
ableToRead, profileHash, _, profileNetworkType, profileAuthor, _, _, _, err := readProfiles.ReadProfileAndHash(false, contentBytes)
|
|
if (err != nil) { return nil, err }
|
|
if (ableToRead == false){
|
|
return nil, errors.New("ReadDecryptedServerRequest_BroadcastContent not verifying profile is valid.")
|
|
}
|
|
if (profileNetworkType != networkType){
|
|
// Requestor must be malicious
|
|
// They should only broadcast content which belongs to our networkType.
|
|
contentAcceptedInfoMap[string(profileHash[:])] = false
|
|
continue
|
|
}
|
|
|
|
hostModeEnabled, isWithinMyRange, err := myRanges.CheckIfIdentityHashIsWithinMyHostedRange(profileAuthor)
|
|
if (err != nil) { return nil, err }
|
|
if (hostModeEnabled == false){
|
|
hostModeDisabled = true
|
|
contentAcceptedInfoMap[string(profileHash[:])] = false
|
|
continue
|
|
}
|
|
|
|
contentAcceptedInfoMap[string(profileHash[:])] = isWithinMyRange
|
|
|
|
if (isWithinMyRange == true){
|
|
|
|
// We add profile to database
|
|
|
|
profileIsWellFormed, addedProfileHash, err := profileStorage.AddUserProfile(contentBytes)
|
|
if (err != nil){ return nil, err }
|
|
if (profileIsWellFormed == false){
|
|
return nil, errors.New("AddUserProfile not verifying profile the same way ReadProfile is")
|
|
}
|
|
if (addedProfileHash != profileHash){
|
|
return nil, errors.New("AddUserProfile returning mismatched profile hash")
|
|
}
|
|
}
|
|
|
|
continue
|
|
}
|
|
if (contentTypeToBroadcast == "Review"){
|
|
|
|
ableToRead, reviewHash, _, reviewNetworkType, _, _, reviewType, reviewedHash, _, _, err := readReviews.ReadReviewAndHash(false, contentBytes)
|
|
if (err != nil) { return nil, err }
|
|
if (ableToRead == false){
|
|
return nil, errors.New("ReadDecryptedServerRequest_BroadcastContent not verifying review is valid.")
|
|
}
|
|
if (reviewNetworkType != networkType){
|
|
// Requestor must be malicious
|
|
// They should only broadcast content which belongs to our networkType.
|
|
contentAcceptedInfoMap[string(reviewHash[:])] = false
|
|
continue
|
|
}
|
|
|
|
//Outputs:
|
|
// -bool: Host mode is enabled
|
|
// -bool: We will host review
|
|
// -error
|
|
checkIfWeWillHostReview := func()(bool, bool, error){
|
|
|
|
if (reviewType == "Message"){
|
|
|
|
if (len(reviewedHash) != 26){
|
|
reviewedHashHex := encoding.EncodeBytesToHexString(reviewedHash)
|
|
return false, false, errors.New("ReadReview returning invalid length reviewedHash for Message review: " + reviewedHashHex)
|
|
}
|
|
|
|
reviewedMessageHash := [26]byte(reviewedHash)
|
|
|
|
metadataExists, _, messageNetworkType, _, messageInbox, _, err := contentMetadata.GetMessageMetadata(reviewedMessageHash)
|
|
if (err != nil) { return false, false, err }
|
|
if (metadataExists == false){
|
|
// We cannot accept reviews for messages whose metadata we do not know
|
|
// This is because we cannot seed reviews for messages whose metadata we do not know
|
|
return true, false, nil
|
|
}
|
|
if (messageNetworkType != reviewNetworkType){
|
|
// The review is reviewing a message from a different network type
|
|
// It is a malicious review. We will not host it.
|
|
return true, false, nil
|
|
}
|
|
|
|
hostModeEnabled, isWithinMyRange, err := myRanges.CheckIfMessageInboxIsWithinMyHostedRange(messageInbox)
|
|
if (err != nil) { return false, false, err }
|
|
|
|
return hostModeEnabled, isWithinMyRange, nil
|
|
}
|
|
// reviewType == "Identity" or "Profile" or "Attribute"
|
|
|
|
//Outputs:
|
|
// -bool: Reviewed identity hash is known
|
|
// -bool: Review is malicious
|
|
// -[16]byte: Reviewed identity hash
|
|
// -error
|
|
getReviewedIdentityHash := func()(bool, bool, [16]byte, error){
|
|
|
|
if (reviewType == "Identity"){
|
|
|
|
if (len(reviewedHash) != 16){
|
|
reviewedHashHex := encoding.EncodeBytesToHexString(reviewedHash)
|
|
return false, false, [16]byte{}, errors.New("ReadReview returning invalid length reviewedHash for Identity review: " + reviewedHashHex)
|
|
}
|
|
|
|
reviewedIdentityHash := [16]byte(reviewedHash)
|
|
|
|
return true, false, reviewedIdentityHash, nil
|
|
}
|
|
if (reviewType == "Profile"){
|
|
|
|
if (len(reviewedHash) != 28){
|
|
reviewedHashHex := encoding.EncodeBytesToHexString(reviewedHash)
|
|
return false, false, [16]byte{}, errors.New("ReadReview returning invalid length reviewedHash for Profile review: " + reviewedHashHex)
|
|
}
|
|
|
|
reviewedProfileHash := [28]byte(reviewedHash)
|
|
|
|
metadataExists, _, profileNetworkType, reviewedProfileAuthor, _, _, _, _, err := contentMetadata.GetProfileMetadata(reviewedProfileHash)
|
|
if (err != nil) { return false, false, [16]byte{}, err }
|
|
if (metadataExists == false){
|
|
return false, false, [16]byte{}, nil
|
|
}
|
|
if (profileNetworkType != reviewNetworkType){
|
|
// Review is reviewing a profile from a different network type
|
|
// Review and author of review are malicious
|
|
return true, true, [16]byte{}, nil
|
|
}
|
|
|
|
return true, false, reviewedProfileAuthor, nil
|
|
}
|
|
if (reviewType == "Attribute"){
|
|
|
|
if (len(reviewedHash) != 27){
|
|
reviewedHashHex := encoding.EncodeBytesToHexString(reviewedHash)
|
|
return false, false, [16]byte{}, errors.New("ReadReview returning invalid length reviewedHash for Attribute review: " + reviewedHashHex)
|
|
}
|
|
|
|
reviewedAttributeHash := [27]byte(reviewedHash)
|
|
|
|
metadataExists, _, authorIdentityHash, attributeNetworkType, _, err := profileStorage.GetProfileAttributeMetadata(reviewedAttributeHash)
|
|
if (err != nil) { return false, false, [16]byte{}, err }
|
|
if (metadataExists == false){
|
|
return false, false, [16]byte{}, nil
|
|
}
|
|
if (attributeNetworkType != reviewNetworkType){
|
|
// Review is reviewing an attribute from a different network type
|
|
// Review and author of review are malicious
|
|
return true, true, [16]byte{}, nil
|
|
}
|
|
|
|
return true, false, authorIdentityHash, nil
|
|
}
|
|
|
|
return false, false, [16]byte{}, errors.New("ReadReview returning invalid reviewType: " + reviewType)
|
|
}
|
|
|
|
reviewedIdentityHashIsKnown, reviewIsMalicious, reviewedIdentityHash, err := getReviewedIdentityHash()
|
|
if (err != nil) { return false, false, err }
|
|
if (reviewedIdentityHashIsKnown == false){
|
|
return true, false, nil
|
|
}
|
|
if (reviewIsMalicious == true){
|
|
return true, false, nil
|
|
}
|
|
|
|
hostModeEnabled, isWithinMyRange, err := myRanges.CheckIfIdentityHashIsWithinMyHostedRange(reviewedIdentityHash)
|
|
if (err != nil) { return false, false, err }
|
|
|
|
return hostModeEnabled, isWithinMyRange, nil
|
|
}
|
|
|
|
hostModeIsEnabled, weWillHostReview, err := checkIfWeWillHostReview()
|
|
if (err != nil) { return nil, err }
|
|
if (hostModeIsEnabled == false){
|
|
hostModeDisabled = true
|
|
contentAcceptedInfoMap[string(reviewHash[:])] = false
|
|
continue
|
|
}
|
|
if (weWillHostReview == false){
|
|
contentAcceptedInfoMap[string(reviewHash[:])] = false
|
|
continue
|
|
}
|
|
|
|
contentAcceptedInfoMap[string(reviewHash[:])] = true
|
|
|
|
// We add review to database
|
|
|
|
reviewIsWellFormed, err := reviewStorage.AddReview(contentBytes)
|
|
if (err != nil) { return nil, err }
|
|
if (reviewIsWellFormed == false){
|
|
return nil, errors.New("ReadReview not verifying review the same way that AddReview is")
|
|
}
|
|
|
|
continue
|
|
}
|
|
if (contentTypeToBroadcast == "Report"){
|
|
|
|
ableToRead, reportHash, _, reportNetworkType, _, reportType, reportedHash, _, err := readReports.ReadReportAndHash(false, contentBytes)
|
|
if (err != nil) { return nil, err }
|
|
if (ableToRead == false){
|
|
return nil, errors.New("ReadDecryptedServerRequest_BroadcastContent not verifying report")
|
|
}
|
|
if (reportNetworkType != networkType){
|
|
// Requestor must be malicious
|
|
// They should only broadcast content which belongs to our networkType.
|
|
contentAcceptedInfoMap[string(reportHash[:])] = false
|
|
continue
|
|
}
|
|
|
|
//Outputs:
|
|
// -bool: Host mode enabled
|
|
// -bool: We will host Report
|
|
// -error
|
|
checkIfWeWillHostReport := func()(bool, bool, error){
|
|
|
|
if (reportType == "Message"){
|
|
|
|
// We see if we are hosting the reported message
|
|
|
|
if (len(reportedHash) != 26){
|
|
reportedHashHex := encoding.EncodeBytesToHexString(reportedHash)
|
|
return false, false, errors.New("ReadReport returning invalid length reportedHash for Message report: " + reportedHashHex)
|
|
}
|
|
|
|
reportedMessageHash := [26]byte(reportedHash)
|
|
|
|
metadataExists, _, messageNetworkType, _, messageInbox, _, err := contentMetadata.GetMessageMetadata(reportedMessageHash)
|
|
if (err != nil) { return false, false, err }
|
|
if (metadataExists == false){
|
|
// We cannot accept reports for messages whose metadata we do not know
|
|
// This is because we cannot seed reports for messages whose metadata we do not know
|
|
return true, false, nil
|
|
}
|
|
if (messageNetworkType != reportNetworkType){
|
|
// Report is reporting a message from a different networkType
|
|
// Report and report author must be malicious
|
|
return true, false, nil
|
|
}
|
|
|
|
hostModeEnabled, isWithinMyRange, err := myRanges.CheckIfMessageInboxIsWithinMyHostedRange(messageInbox)
|
|
if (err != nil) { return false, false, err }
|
|
|
|
return hostModeEnabled, isWithinMyRange, nil
|
|
}
|
|
// reportType = "Identity" or "Profile" or "Attribute"
|
|
|
|
//Outputs:
|
|
// -bool: Reported identity hash is known
|
|
// -bool: Report is malicious
|
|
// -[16]byte: Reported identity hash
|
|
// -error
|
|
getReportedIdentityHash := func()(bool, bool, [16]byte, error){
|
|
|
|
if (reportType == "Identity"){
|
|
|
|
if (len(reportedHash) != 16){
|
|
reportedHashHex := encoding.EncodeBytesToHexString(reportedHash)
|
|
return false, false, [16]byte{}, errors.New("ReadReport returning invalid length reportedHash for Identity report: " + reportedHashHex)
|
|
}
|
|
|
|
reportedIdentityHash := [16]byte(reportedHash)
|
|
|
|
return true, false, reportedIdentityHash, nil
|
|
}
|
|
if (reportType == "Profile"){
|
|
|
|
if (len(reportedHash) != 28){
|
|
reportedHashHex := encoding.EncodeBytesToHexString(reportedHash)
|
|
return false, false, [16]byte{}, errors.New("ReadReport returning invalid length reportedHash for Profile report: " + reportedHashHex)
|
|
}
|
|
|
|
reportedProfileHash := [28]byte(reportedHash)
|
|
|
|
metadataExists, _, profileNetworkType, reportedProfileAuthor, _, _, _, _, err := contentMetadata.GetProfileMetadata(reportedProfileHash)
|
|
if (err != nil) { return false, false, [16]byte{}, err }
|
|
if (metadataExists == false){
|
|
return false, false, [16]byte{}, nil
|
|
}
|
|
if (profileNetworkType != reportNetworkType){
|
|
// Report is reporting a profile from a different networkType
|
|
// Report and report author must be malicious
|
|
return true, true, [16]byte{}, nil
|
|
}
|
|
|
|
return true, false, reportedProfileAuthor, nil
|
|
}
|
|
if (reportType == "Attribute"){
|
|
|
|
if (len(reportedHash) != 27){
|
|
reportedHashHex := encoding.EncodeBytesToHexString(reportedHash)
|
|
return false, false, [16]byte{}, errors.New("ReadReport returning invalid length reportedHash for Attribute report: " + reportedHashHex)
|
|
}
|
|
|
|
reportedAttributeHash := [27]byte(reportedHash)
|
|
|
|
metadataExists, _, authorIdentityHash, attributeNetworkType, _, err := profileStorage.GetProfileAttributeMetadata(reportedAttributeHash)
|
|
if (err != nil) { return false, false, [16]byte{}, err }
|
|
if (metadataExists == false){
|
|
return false, false, [16]byte{}, nil
|
|
}
|
|
if (attributeNetworkType != reportNetworkType){
|
|
// Report is reporting an attribute from a different networkType
|
|
// Report and report author must be malicious
|
|
return true, true, [16]byte{}, nil
|
|
}
|
|
|
|
return true, false, authorIdentityHash, nil
|
|
}
|
|
|
|
return false, false, [16]byte{}, errors.New("ReadReport returning invalid reportType: " + reportType)
|
|
}
|
|
|
|
reportedIdentityHashIsKnown, reportIsMalicious, reportedIdentityHash, err := getReportedIdentityHash()
|
|
if (err != nil) { return false, false, err }
|
|
if (reportedIdentityHashIsKnown == false){
|
|
return true, false, nil
|
|
}
|
|
if (reportIsMalicious == true){
|
|
return true, false, nil
|
|
}
|
|
|
|
hostModeEnabled, isWithinMyRange, err := myRanges.CheckIfIdentityHashIsWithinMyHostedRange(reportedIdentityHash)
|
|
if (err != nil) { return false, false, err }
|
|
|
|
return hostModeEnabled, isWithinMyRange, nil
|
|
}
|
|
|
|
hostModeIsEnabled, weWillHostReport, err := checkIfWeWillHostReport()
|
|
if (err != nil) { return nil, err }
|
|
if (hostModeIsEnabled == false){
|
|
hostModeDisabled = true
|
|
contentAcceptedInfoMap[string(reportHash[:])] = false
|
|
continue
|
|
}
|
|
if (weWillHostReport == false){
|
|
contentAcceptedInfoMap[string(reportHash[:])] = false
|
|
continue
|
|
}
|
|
|
|
contentAcceptedInfoMap[string(reportHash[:])] = true
|
|
|
|
// We add report to database
|
|
|
|
reportIsWellFormed, err := reportStorage.AddReport(contentBytes)
|
|
if (err != nil) { return nil, err }
|
|
if (reportIsWellFormed == false){
|
|
return nil, errors.New("ReadReport not verifying report the same way as AddReport is")
|
|
}
|
|
|
|
continue
|
|
}
|
|
|
|
return nil, errors.New("ReadDecryptedServerRequest_BroadcastContent returning invalid contentTypeToBroadcast: " + contentTypeToBroadcast)
|
|
}
|
|
|
|
if (hostModeDisabled == true){
|
|
|
|
// Host mode is disabled, so we cannot accept any content
|
|
|
|
for contentHash, _ := range contentAcceptedInfoMap{
|
|
contentAcceptedInfoMap[contentHash] = false
|
|
}
|
|
}
|
|
|
|
responseBytes, err := serverResponse.CreateServerResponse_BroadcastContent(myHostPublicIdentityKey, myHostPrivateIdentityKey, connectionKey, requestIdentifier, contentAcceptedInfoMap)
|
|
if (err != nil) { return nil, err }
|
|
|
|
return responseBytes, nil
|
|
}
|
|
|
|
//TODO: GetAddressDeposits, GetFundedStatuses
|
|
|
|
// Request contains unknown requestType
|
|
return invalidRequestResponse, nil
|
|
}
|
|
|
|
|
|
|