seekia/internal/network/craftResponses/craftResponses.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
}