// sendRequests provides functions for making requests to Seekia hosts // Each function provides a way to send a server request to a host through an active connection // This package is imported by queryHosts. // queryHosts is a higher level package which provides functions to split requests up, to save retrieved data, and more package sendRequests //TODO: Add if request successful, remove host from unreachable list //TODO: Verify that input does not exceed maximum size for request of that type //TODO: Add ability to handle busy responses // If host is busy, we will keep track of that in a new package and not try to recontact them for a while import "seekia/internal/byteRange" import "seekia/internal/encoding" import "seekia/internal/helpers" import "seekia/internal/identity" import "seekia/internal/messaging/readMessages" import "seekia/internal/moderation/readReports" import "seekia/internal/moderation/readReviews" import "seekia/internal/network/maliciousHosts" import "seekia/internal/network/mateCriteria" import "seekia/internal/network/peerClient" import "seekia/internal/network/serverRequest" import "seekia/internal/network/serverResponse" import "seekia/internal/parameters/readParameters" import "seekia/internal/profiles/readProfiles" import "seekia/internal/readContent" import "bytes" import "errors" import "slices" //Outputs: // -bool: Download successsful // -map[string]int64: Map of ParametersType -> Parameters Creation time // -error func GetParametersInfoFromHost(connectionIdentifier [21]byte, hostIdentityHash [16]byte, networkType byte)(bool, map[string]int64, error){ connectionExists, connectionHostIdentityHash, connectionKey, connectionNetworkType, err := peerClient.GetConnectionMetadata(connectionIdentifier) if (err != nil) { return false, nil, err } if (connectionExists == false){ return false, nil, nil } if (connectionHostIdentityHash != hostIdentityHash){ return false, nil, errors.New("GetParametersInfoFromHost called with hostIdentityHash which does not match connection metadata.") } if (connectionNetworkType != networkType){ return false, nil, errors.New("GetParametersInfoFromHost called with networkType which does not match connection metadata.") } requestBytes, requestIdentifier, err := serverRequest.CreateServerRequest_GetParametersInfo(hostIdentityHash, connectionKey, networkType) if (err != nil) { return false, nil, err } requestSuccessful, responseData, err := peerClient.SendRequestThroughConnection(connectionIdentifier, requestBytes) if (err != nil) { return false, nil, err } if (requestSuccessful == false){ return false, nil, nil } ableToRead, requestIdentifier_Received, hostIdentityHash_Received, parametersInfoMap, err := serverResponse.ReadServerResponse_GetParametersInfo(responseData, connectionKey) if (err != nil) { return false, nil, err } if (ableToRead == false){ // Host sent invalid response, must be malicious err := maliciousHosts.AddHostToMaliciousHostsList(hostIdentityHash) if (err != nil){ return false, nil, err } return false, nil, nil } // Now we check to make sure response is valid checkIfResponseIsValid := func()(bool, error){ if (requestIdentifier != requestIdentifier_Received){ // Host sent invalid response, must be malicious return false, nil } if (hostIdentityHash != hostIdentityHash_Received){ // Host sent invalid response, must be malicious return false, nil } return true, nil } responseIsValid, err := checkIfResponseIsValid() if (err != nil) { return false, nil, err } if (responseIsValid == false){ err := maliciousHosts.AddHostToMaliciousHostsList(hostIdentityHash) if (err != nil){ return false, nil, err } return false, nil, nil } return true, parametersInfoMap, nil } //Outputs: // -bool: Download successful (could be unsuccessful because host keys not found, host is malicious, internet connection down, and more) // -[][]byte: List of parameters // -error func GetParametersFromHost( connectionIdentifier [21]byte, hostIdentityHash [16]byte, networkType byte, parametersTypesToRetrieveList []string)(bool, [][]byte, error){ connectionExists, connectionHostIdentityHash, connectionKey, connectionNetworkType, err := peerClient.GetConnectionMetadata(connectionIdentifier) if (err != nil) { return false, nil, err } if (connectionExists == false){ return false, nil, nil } if (connectionHostIdentityHash != hostIdentityHash){ return false, nil, errors.New("GetParametersFromHost called with hostIdentityHash which does not match connection metadata.") } if (connectionNetworkType != networkType){ return false, nil, errors.New("GetParametersFromHost called with networkType which does not match connection metadata.") } requestBytes, requestIdentifier, err := serverRequest.CreateServerRequest_GetParameters(hostIdentityHash, connectionKey, networkType, parametersTypesToRetrieveList) if (err != nil) { return false, nil, err } requestSuccessful, responseData, err := peerClient.SendRequestThroughConnection(connectionIdentifier, requestBytes) if (err != nil) { return false, nil, err } if (requestSuccessful == false){ return false, nil, nil } ableToRead, requestIdentifier_Received, hostIdentityHash_Received, parametersList, err := serverResponse.ReadServerResponse_GetParameters(responseData, connectionKey) if (err != nil) { return false, nil, err } if (ableToRead == false){ // Peer sent invalid response, must be malicious err := maliciousHosts.AddHostToMaliciousHostsList(hostIdentityHash) if (err != nil) { return false, nil, err } return false, nil, nil } // Now we check to make sure response is valid based on input request information checkIfResponseIsValid := func()(bool, error){ if (requestIdentifier != requestIdentifier_Received){ // Host sent invalid response, must be malicious return false, nil } if (hostIdentityHash != hostIdentityHash_Received){ return false, nil } for _, parametersBytes := range parametersList{ ableToRead, _, parametersNetworkType, _, parametersType, _, _, err := readParameters.ReadParameters(false, parametersBytes) if (err != nil) { return false, err } if (ableToRead == false){ return false, errors.New("ReadServerResponse_GetParameters not verifying network parameters") } if (parametersNetworkType != networkType){ // We did not request parameters for this networkType. return false, nil } isExpected := slices.Contains(parametersTypesToRetrieveList, parametersType) if (isExpected == false){ // We did not request this parameters type. Response is malformed. return false, nil } } return true, nil } responseIsValid, err := checkIfResponseIsValid() if (err != nil) { return false, nil, err } if (responseIsValid == false){ // Peer sent invalid response, must be malicious err := maliciousHosts.AddHostToMaliciousHostsList(hostIdentityHash) if (err != nil) { return false, nil, err } return false, nil, nil } return true, parametersList, nil } //Outputs: // -bool: Download successful (could be unsuccessful because host keys not found, host is malicious, internet connection down, and more) // -[]serverResponse.ProfileInfoStruct: Profiles info map list // -error func GetProfilesInfoFromHost( connectionIdentifier [21]byte, hostIdentityHash [16]byte, networkType byte, profileTypeToRetrieve string, rangeStart [16]byte, rangeEnd [16]byte, identityHashesList [][16]byte, criteria []byte, getNewestProfilesOnly bool, getViewableProfilesOnly bool)(bool, []serverResponse.ProfileInfoStruct, error){ connectionExists, connectionHostIdentityHash, connectionKey, connectionNetworkType, err := peerClient.GetConnectionMetadata(connectionIdentifier) if (err != nil) { return false, nil, err } if (connectionExists == false){ return false, nil, nil } if (connectionHostIdentityHash != hostIdentityHash){ return false, nil, errors.New("GetProfilesInfoFromHost called with hostIdentityHash which does not match connection metadata.") } if (connectionNetworkType != networkType){ return false, nil, errors.New("GetProfilesInfoFromHost called with networkType which does not match connection metadata.") } acceptableProfileVersionsList := []int{1} requestBytes, requestIdentifier, err := serverRequest.CreateServerRequest_GetProfilesInfo(hostIdentityHash, connectionKey, networkType, acceptableProfileVersionsList, profileTypeToRetrieve, rangeStart, rangeEnd, identityHashesList, criteria, getNewestProfilesOnly, getViewableProfilesOnly) if (err != nil) { return false, nil, err } requestSuccessful, responseData, err := peerClient.SendRequestThroughConnection(connectionIdentifier, requestBytes) if (err != nil) { return false, nil, err } if (requestSuccessful == false){ return false, nil, nil } ableToRead, requestIdentifier_Received, hostIdentityHash_Received, profileInfoObjectsList, err := serverResponse.ReadServerResponse_GetProfilesInfo(responseData, connectionKey) if (err != nil) { return false, nil, err } if (ableToRead == false){ // Peer sent invalid response, must be malicious err := maliciousHosts.AddHostToMaliciousHostsList(hostIdentityHash) if (err != nil){ return false, nil, err } return false, nil, nil } // Now we check to make sure response is valid based on input request information checkIfResponseIsValid := func()(bool, error){ if (requestIdentifier != requestIdentifier_Received){ // Host sent invalid response, must be malicious return false, nil } if (hostIdentityHash != hostIdentityHash_Received){ // Peer sent invalid response, must be malicious return false, nil } // Now we verify received profile identity hashes fulfill request filters // We use map to make sure that only 1 profile hash per identity is returned (if getNewestProfilesOnly == true) // Map structure: Identity Hash -> Nothing identitiesMap := make(map[[16]byte]struct{}) for _, profileInfoObject := range profileInfoObjectsList{ receivedProfileAuthor := profileInfoObject.ProfileAuthor identityType, err := identity.GetIdentityTypeFromIdentityHash(receivedProfileAuthor) if (err != nil){ receivedProfileAuthorHex := encoding.EncodeBytesToHexString(receivedProfileAuthor[:]) return false, errors.New("ReadServerResponse_GetProfilesInfo not verifying profileInfoObject receivedProfileAuthor: " + receivedProfileAuthorHex) } if (identityType != profileTypeToRetrieve){ return false, nil } if (len(identityHashesList) != 0){ identityIsInRequestedList := slices.Contains(identityHashesList, receivedProfileAuthor) if (identityIsInRequestedList == false){ return false, nil } } isWithinRange, err := byteRange.CheckIfIdentityHashIsWithinRange(rangeStart, rangeEnd, receivedProfileAuthor) if (err != nil) { return false, err } if (isWithinRange == false){ return false, nil } if (getNewestProfilesOnly == true){ _, exists := identitiesMap[receivedProfileAuthor] if (exists == true){ // We received two profiles with the same author in a getNewestProfilesOnly response. return false, nil } identitiesMap[receivedProfileAuthor] = struct{}{} } } return true, nil } responseIsValid, err := checkIfResponseIsValid() if (err != nil) { return false, nil, err } if (responseIsValid == false){ err := maliciousHosts.AddHostToMaliciousHostsList(hostIdentityHash) if (err != nil){ return false, nil, err } return false, nil, nil } return true, profileInfoObjectsList, nil } //Outputs: // -bool: Download successful (could be unsuccessful because host keys not found, host is malicious, internet connection down, and more) // -[][]byte: List of profiles // -error func GetProfilesFromHost( connectionIdentifier [21]byte, hostIdentityHash [16]byte, networkType byte, profileTypeToRetrieve string, profileHashesList [][28]byte, expectedProfileIdentityHashesMap map[[28]byte][16]byte, // Profile Hash -> Profile Identity hash expectedProfileCreationTimesMap map[[28]byte]int64, // Profile Hash -> Profile Creation Time expectedCriteria []byte)(bool, [][]byte, error){ connectionExists, connectionHostIdentityHash, connectionKey, connectionNetworkType, err := peerClient.GetConnectionMetadata(connectionIdentifier) if (err != nil) { return false, nil, err } if (connectionExists == false){ return false, nil, nil } if (connectionHostIdentityHash != hostIdentityHash){ return false, nil, errors.New("GetProfilesFromHost called with hostIdentityHash which does not match connection metadata.") } if (connectionNetworkType != networkType){ return false, nil, errors.New("GetProfilesFromHost called with networkType which does not match connection metadata.") } requestBytes, requestIdentifier, err := serverRequest.CreateServerRequest_GetProfiles(hostIdentityHash, connectionKey, networkType, profileTypeToRetrieve, profileHashesList) if (err != nil) { return false, nil, err } requestSuccessful, responseData, err := peerClient.SendRequestThroughConnection(connectionIdentifier, requestBytes) if (err != nil) { return false, nil, err } if (requestSuccessful == false){ return false, nil, nil } ableToRead, requestIdentifier_Received, hostIdentityHash_Received, profilesList, err := serverResponse.ReadServerResponse_GetProfiles(responseData, connectionKey) if (err != nil) { return false, nil, err } if (ableToRead == false){ // Peer sent invalid response, must be malicious err := maliciousHosts.AddHostToMaliciousHostsList(hostIdentityHash) if (err != nil) { return false, nil, err } return false, nil, nil } // Now we check to make sure response is valid based on input request information checkIfResponseIsValid := func()(bool, error){ if (requestIdentifier != requestIdentifier_Received){ // Host sent invalid response, must be malicious return false, nil } if (hostIdentityHash != hostIdentityHash_Received){ return false, nil } if (len(profilesList) > len(profileHashesList)){ return false, nil } for _, profileBytes := range profilesList{ ableToRead, profileHash, profileVersion, profileNetworkType, profileIdentityHash, profileCreationTime, _, rawProfileMap, err := readProfiles.ReadProfileAndHash(false, profileBytes) if (err != nil) { return false, err } if (ableToRead == false){ return false, errors.New("ReadServerResponse_GetProfiles not verifying received profile is valid.") } profileHashIsExpected := slices.Contains(profileHashesList, profileHash) if (profileHashIsExpected == false){ return false, nil } if (profileNetworkType != networkType){ // The host must have sent us a different networkType profile when we requested profilesInfo return false, nil } expectedProfileIdentityHash, profileExists := expectedProfileIdentityHashesMap[profileHash] if (profileExists == false){ return false, errors.New("ExpectedProfileIdentityHashesMap missing entry for profile contained in ProfileHashesList") } if (profileIdentityHash != expectedProfileIdentityHash){ return false, nil } expectedProfileCreationTime, exists := expectedProfileCreationTimesMap[profileHash] if (exists == false){ return false, errors.New("expectedProfileCreationTimesMap missing entry for profile contained in ProfileHashesList") } if (profileCreationTime != expectedProfileCreationTime){ // Profile is does not fulfill the expected CreationTime return false, nil } if (expectedCriteria != nil){ criteriaIsValid, fulfillsCriteria, err := mateCriteria.CheckIfMateProfileFulfillsCriteria(false, profileVersion, rawProfileMap, expectedCriteria) if (err != nil) { return false, err } if (criteriaIsValid == false){ return false, errors.New("GetProfilesFromHost called with invalid expectedCriteria") } if (fulfillsCriteria == false){ return false, nil } } } return true, nil } responseIsValid, err := checkIfResponseIsValid() if (err != nil) { return false, nil, err } if (responseIsValid == false){ // Peer sent invalid response, must be malicious err := maliciousHosts.AddHostToMaliciousHostsList(hostIdentityHash) if (err != nil) { return false, nil, err } return false, nil, nil } return true, profilesList, nil } //Outputs: // -bool: Download successful (could be unsuccessful because host keys not found, host is malicious, internet connection down, and more) // -[][26]byte: Received message hashes list // -error func GetMessageHashesListFromHost( connectionIdentifier [21]byte, hostIdentityHash [16]byte, networkType byte, rangeStart [10]byte, rangeEnd [10]byte, inboxesToRetrieveList [][10]byte, getViewableMessagesOnly bool, getDecryptableMessagesOnly bool)(bool, [][26]byte, error){ connectionExists, connectionHostIdentityHash, connectionKey, connectionNetworkType, err := peerClient.GetConnectionMetadata(connectionIdentifier) if (err != nil) { return false, nil, err } if (connectionExists == false){ return false, nil, nil } if (connectionHostIdentityHash != hostIdentityHash){ return false, nil, errors.New("GetMessageHashesListFromHost called with hostIdentityHash which does not match connection metadata.") } if (connectionNetworkType != networkType){ return false, nil, errors.New("GetMessageHashesListFromHost called with networkType which does not match connection metadata.") } acceptableMessageVersionsList := []int{1} requestBytes, requestIdentifier, err := serverRequest.CreateServerRequest_GetMessageHashesList(hostIdentityHash, connectionKey, networkType, acceptableMessageVersionsList, rangeStart, rangeEnd, inboxesToRetrieveList, getViewableMessagesOnly, getDecryptableMessagesOnly) if (err != nil) { return false, nil, err } requestSuccessful, responseData, err := peerClient.SendRequestThroughConnection(connectionIdentifier, requestBytes) if (err != nil) { return false, nil, err } if (requestSuccessful == false){ return false, nil, nil } ableToRead, requestIdentifier_Received, hostIdentityHash_Received, messageHashesList_Received, err := serverResponse.ReadServerResponse_GetMessageHashesList(responseData, connectionKey) if (err != nil) { return false, nil, err } if (ableToRead == false){ // Peer sent invalid response, must be malicious err := maliciousHosts.AddHostToMaliciousHostsList(hostIdentityHash) if (err != nil){ return false, nil, err } return false, nil, nil } // Now we check to make sure response is valid based on input request information checkIfResponseIsValid := func()(bool, error){ if (requestIdentifier != requestIdentifier_Received){ // Host sent invalid response, must be malicious return false, nil } if (hostIdentityHash != hostIdentityHash_Received){ // Peer sent invalid response, must be malicious return false, nil } return true, nil } responseIsValid, err := checkIfResponseIsValid() if (err != nil) { return false, nil, err } if (responseIsValid == false){ err := maliciousHosts.AddHostToMaliciousHostsList(hostIdentityHash) if (err != nil){ return false, nil, err } return false, nil, nil } return true, messageHashesList_Received, nil } //Outputs: // -bool: Download successful (could be unsuccessful because host keys not found, host is malicious, internet connection down, and more) // -[][]byte: List of messages // -error func GetMessagesFromHost( connectionIdentifier [21]byte, hostIdentityHash [16]byte, networkType byte, messageHashesList [][26]byte, expectedInboxRangeStart [10]byte, expectedInboxRangeEnd [10]byte, expectedInboxesList [][10]byte)(bool, [][]byte, error){ connectionExists, connectionHostIdentityHash, connectionKey, connectionNetworkType, err := peerClient.GetConnectionMetadata(connectionIdentifier) if (err != nil) { return false, nil, err } if (connectionExists == false){ return false, nil, nil } if (connectionHostIdentityHash != hostIdentityHash){ return false, nil, errors.New("GetMessagesFromHost called with hostIdentityHash which does not match connection metadata.") } if (connectionNetworkType != networkType){ return false, nil, errors.New("GetMessagesFromHost called with networkType which does not match connection metadata.") } requestBytes, requestIdentifier, err := serverRequest.CreateServerRequest_GetMessages(hostIdentityHash, connectionKey, networkType, messageHashesList) if (err != nil) { return false, nil, err } requestSuccessful, responseData, err := peerClient.SendRequestThroughConnection(connectionIdentifier, requestBytes) if (err != nil) { return false, nil, err } if (requestSuccessful == false){ return false, nil, nil } ableToRead, requestIdentifier_Received, hostIdentityHash_Received, messagesList, err := serverResponse.ReadServerResponse_GetMessages(responseData, connectionKey) if (err != nil) { return false, nil, err } if (ableToRead == false){ // Peer sent invalid response, must be malicious err := maliciousHosts.AddHostToMaliciousHostsList(hostIdentityHash) if (err != nil) { return false, nil, err } return false, nil, nil } // Now we check to make sure response is valid based on input request information checkIfResponseIsValid := func()(bool, error){ if (requestIdentifier != requestIdentifier_Received){ // Host sent invalid response, must be malicious return false, nil } if (hostIdentityHash != hostIdentityHash_Received){ return false, nil } for _, messageBytes := range messagesList{ ableToRead, messageHash, _, messageNetworkType, messageInbox, _, _, _, _, _, _, err := readMessages.ReadChatMessagePublicDataAndHash(false, messageBytes) if (err != nil) { return false, err } if (ableToRead == false){ return false, errors.New("ReadServerResponse_GetMessages not verifying each message.") } isExpected := slices.Contains(messageHashesList, messageHash) if (isExpected == false){ return false, nil } if (messageNetworkType != networkType){ // Host must have sent us a different networkType messageHash when we got messageHashesList response return false, nil } if (len(expectedInboxesList) != 0){ messageInboxIsExpected := slices.Contains(expectedInboxesList, messageInbox) if (messageInboxIsExpected == false){ return false, nil } } else { inboxIsWithinRange, err := byteRange.CheckIfInboxIsWithinRange(expectedInboxRangeStart, expectedInboxRangeEnd, messageInbox) if (err != nil) { return false, err } if (inboxIsWithinRange == false){ return false, nil } } } return true, nil } responseIsValid, err := checkIfResponseIsValid() if (err != nil) { return false, nil, err } if (responseIsValid == false){ // Peer sent invalid response, must be malicious err := maliciousHosts.AddHostToMaliciousHostsList(hostIdentityHash) if (err != nil) { return false, nil, err } return false, nil, nil } return true, messagesList, nil } //Outputs: // -bool: Download successful (could be unsuccessful because host keys not found, host is malicious, internet connection down, and more) // -map[[29]byte][]byte: Received reviews info map (Review Hash -> Reviewed Hash) // -error func GetIdentityReviewsInfoFromHost( connectionIdentifier [21]byte, hostIdentityHash [16]byte, networkType byte, identityTypeToRetrieve string, rangeStart [16]byte, rangeEnd [16]byte, reviewedIdentityHashesList [][16]byte, reviewersList [][16]byte)(bool, map[[29]byte][]byte, error){ connectionExists, connectionHostIdentityHash, connectionKey, connectionNetworkType, err := peerClient.GetConnectionMetadata(connectionIdentifier) if (err != nil) { return false, nil, err } if (connectionExists == false){ return false, nil, nil } if (connectionHostIdentityHash != hostIdentityHash){ return false, nil, errors.New("GetIdentityReviewsInfoFromHost called with hostIdentityHash which does not match connection metadata.") } if (connectionNetworkType != networkType){ return false, nil, errors.New("GetIdentityReviewsInfoFromHost called with networkType which does not match connection metadata.") } acceptableReviewVersionList := []int{1} requestBytes, requestIdentifier, err := serverRequest.CreateServerRequest_GetIdentityReviewsInfo(hostIdentityHash, connectionKey, networkType, acceptableReviewVersionList, identityTypeToRetrieve, rangeStart, rangeEnd, reviewedIdentityHashesList, reviewersList) if (err != nil) { return false, nil, err } requestSuccessful, responseBytes, err := peerClient.SendRequestThroughConnection(connectionIdentifier, requestBytes) if (err != nil) { return false, nil, err } if (requestSuccessful == false){ return false, nil, nil } ableToRead, requestIdentifier_Received, hostIdentityHash_Received, reviewsInfoMap, err := serverResponse.ReadServerResponse_GetIdentityReviewsInfo(responseBytes, connectionKey) if (err != nil) { return false, nil, err } if (ableToRead == false){ // Peer sent invalid response, must be malicious err := maliciousHosts.AddHostToMaliciousHostsList(hostIdentityHash) if (err != nil){ return false, nil, err } return false, nil, nil } // Now we check to make sure response is valid based on input request information checkIfResponseIsValid := func()(bool, error){ if (requestIdentifier != requestIdentifier_Received){ // Host sent invalid response, must be malicious return false, nil } if (hostIdentityHash != hostIdentityHash_Received){ // Peer sent invalid response, must be malicious return false, nil } // Now we verify received reviews info map fulfills request filters for _, reviewedHash := range reviewsInfoMap{ // reviewedHash is either Profile hash or identity hash or attribute hash reviewedHashType, err := helpers.GetReviewedTypeFromReviewedHash(reviewedHash) if (err != nil) { reviewedHashHex := encoding.EncodeBytesToHexString(reviewedHash) return false, errors.New("ReadServerResponse_GetReviewsInfo not verifying reviewsInfoMap reviewedHash: " + reviewedHashHex) } if (reviewedHashType != "Identity" && reviewedHashType != "Profile" && reviewedHashType != "Attribute"){ // Must be a message hash. Host is malicious. reviewedHashHex := encoding.EncodeBytesToHexString(reviewedHash) return false, errors.New("ReadServerResponse_GetReviewsInfo not verifying reviewsInfoMap reviewedHash: " + reviewedHashHex) } if (reviewedHashType == "Identity"){ if (len(reviewedHash) != 16){ reviewedHashHex := encoding.EncodeBytesToHexString(reviewedHash) return false, errors.New("GetReviewedTypeFromReviewedHash returning Identity for different length reviewedHash: " + reviewedHashHex) } reviewedIdentityHash := [16]byte(reviewedHash) if (len(reviewedIdentityHashesList) == 0){ // We only need to verify identityType if a reviewedHashesList was not requested identityType, err := identity.GetIdentityTypeFromIdentityHash(reviewedIdentityHash) if (err != nil){ reviewedIdentityHashHex := encoding.EncodeBytesToHexString(reviewedIdentityHash[:]) return false, errors.New("GetReviewedTypeFromReviewedHash fails to verify identity hash: " + reviewedIdentityHashHex) } if (identityType != identityTypeToRetrieve){ return false, nil } } isWithinRange, err := byteRange.CheckIfIdentityHashIsWithinRange(rangeStart, rangeEnd, reviewedIdentityHash) if (err != nil) { return false, err } if (isWithinRange == false){ return false, nil } if (len(reviewedIdentityHashesList) != 0){ identityHashIsInRequestedList := slices.Contains(reviewedIdentityHashesList, reviewedIdentityHash) if (identityHashIsInRequestedList == false){ return false, nil } } continue } else if (reviewedHashType == "Profile"){ if (len(reviewedHash) != 28){ reviewedHashHex := encoding.EncodeBytesToHexString(reviewedHash) return false, errors.New("GetReviewedTypeFromReviewedHash returning Profile for different length reviewedHash: " + reviewedHashHex) } reviewedProfileHash := [28]byte(reviewedHash) if (len(reviewedIdentityHashesList) == 0){ // We only need to verify profileType if a reviewedIdentityHashesList was not requested profileType, isDisabled, err := readProfiles.ReadProfileHashMetadata(reviewedProfileHash) if (err != nil) { reviewedProfileHashHex := encoding.EncodeBytesToHexString(reviewedProfileHash[:]) return false, errors.New("ReadServerResponse_GetReviewsInfo not verifying reviewsInfoMap reviewedHash: " + reviewedProfileHashHex) } if (isDisabled == true){ return false, errors.New("ReadServerResponse_GetReviewsInfo not verifying reviewsInfoMap reviewedHash: Profile hash is disabled.") } if (profileType != identityTypeToRetrieve){ return false, nil } } } } return true, nil } responseIsValid, err := checkIfResponseIsValid() if (err != nil) { return false, nil, err } if (responseIsValid == false){ err := maliciousHosts.AddHostToMaliciousHostsList(hostIdentityHash) if (err != nil){ return false, nil, err } return false, nil, nil } return true, reviewsInfoMap, nil } //Outputs: // -bool: Download successful (could be unsuccessful because host keys not found, host is malicious, internet connection down, and more) // -map[[29]byte][26]byte: Received reviews info map (Review Hash -> Reviewed Message Hash) // -error func GetMessageReviewsInfoFromHost( connectionIdentifier [21]byte, hostIdentityHash [16]byte, networkType byte, rangeStart [10]byte, rangeEnd [10]byte, reviewedMessageHashesList [][26]byte, reviewersList [][16]byte)(bool, map[[29]byte][26]byte, error){ connectionExists, connectionHostIdentityHash, connectionKey, connectionNetworkType, err := peerClient.GetConnectionMetadata(connectionIdentifier) if (err != nil) { return false, nil, err } if (connectionExists == false){ return false, nil, nil } if (connectionHostIdentityHash != hostIdentityHash){ return false, nil, errors.New("GetMessageReviewsInfoFromHost called with hostIdentityHash which does not match connection metadata.") } if (connectionNetworkType != networkType){ return false, nil, errors.New("GetMessageReviewsInfoFromHost called with networkType which does not match connection metadata.") } acceptableReviewVersionList := []int{1} requestBytes, requestIdentifier, err := serverRequest.CreateServerRequest_GetMessageReviewsInfo(hostIdentityHash, connectionKey, networkType, acceptableReviewVersionList, rangeStart, rangeEnd, reviewedMessageHashesList, reviewersList) if (err != nil) { return false, nil, err } requestSuccessful, responseBytes, err := peerClient.SendRequestThroughConnection(connectionIdentifier, requestBytes) if (err != nil) { return false, nil, err } if (requestSuccessful == false){ return false, nil, nil } ableToRead, requestIdentifier_Received, hostIdentityHash_Received, reviewsInfoMap, err := serverResponse.ReadServerResponse_GetMessageReviewsInfo(responseBytes, connectionKey) if (err != nil) { return false, nil, err } if (ableToRead == false){ // Peer sent invalid response, must be malicious err := maliciousHosts.AddHostToMaliciousHostsList(hostIdentityHash) if (err != nil){ return false, nil, err } return false, nil, nil } // Now we check to make sure response is valid based on input request information checkIfResponseIsValid := func()(bool, error){ if (requestIdentifier != requestIdentifier_Received){ // Host sent invalid response, must be malicious return false, nil } if (hostIdentityHash != hostIdentityHash_Received){ // Peer sent invalid response, must be malicious return false, nil } // Now we verify received reviews info map fulfills request filters for _, reviewedHash := range reviewsInfoMap{ // reviewedHash is a message hash if (len(reviewedMessageHashesList) != 0){ messageHashIsInRequestedList := slices.Contains(reviewedMessageHashesList, reviewedHash) if (messageHashIsInRequestedList == false){ return false, nil } } } return true, nil } responseIsValid, err := checkIfResponseIsValid() if (err != nil) { return false, nil, err } if (responseIsValid == false){ err := maliciousHosts.AddHostToMaliciousHostsList(hostIdentityHash) if (err != nil){ return false, nil, err } return false, nil, nil } return true, reviewsInfoMap, nil } //Outputs: // -bool: Download successful (could be unsuccessful because host keys not found, host is malicious, internet connection down, and more) // -[][]byte: Retrieved list of reviews // -error func GetReviewsFromHost( connectionIdentifier [21]byte, hostIdentityHash [16]byte, networkType byte, reviewHashesList [][29]byte, expectedReviewsInfoMap map[[29]byte][]byte, // Review Hash -> Reviewed Hash expectedReviewersList [][16]byte)(bool, [][]byte, error){ connectionExists, connectionHostIdentityHash, connectionKey, connectionNetworkType, err := peerClient.GetConnectionMetadata(connectionIdentifier) if (err != nil) { return false, nil, err } if (connectionExists == false){ return false, nil, nil } if (connectionHostIdentityHash != hostIdentityHash){ return false, nil, errors.New("GetReviewsFromHost called with hostIdentityHash which does not match connection metadata.") } if (connectionNetworkType != networkType){ return false, nil, errors.New("GetReviewsFromHost called with networkType which does not match connection metadata.") } requestBytes, requestIdentifier, err := serverRequest.CreateServerRequest_GetReviews(hostIdentityHash, connectionKey, networkType, reviewHashesList) if (err != nil) { return false, nil, err } requestSuccessful, responseData, err := peerClient.SendRequestThroughConnection(connectionIdentifier, requestBytes) if (err != nil) { return false, nil, err } if (requestSuccessful == false){ return false, nil, nil } ableToRead, requestIdentifier_Received, hostIdentityHash_Received, reviewsList, err := serverResponse.ReadServerResponse_GetReviews(responseData, connectionKey) if (err != nil) { return false, nil, err } if (ableToRead == false){ // Peer sent invalid response, must be malicious err := maliciousHosts.AddHostToMaliciousHostsList(hostIdentityHash) if (err != nil) { return false, nil, err } return false, nil, nil } // Now we check to make sure response is valid based on input request information checkIfResponseIsValid := func()(bool, error){ if (requestIdentifier != requestIdentifier_Received){ // Host sent invalid response, must be malicious return false, nil } if (hostIdentityHash != hostIdentityHash_Received){ return false, nil } for _, reviewBytes := range reviewsList{ ableToRead, reviewHash, _, reviewNetworkType, authorIdentityHash, _, _, reviewReviewedHash, _, _, err := readReviews.ReadReviewAndHash(false, reviewBytes) if (err != nil) { return false, err } if (ableToRead == false){ return false, errors.New("ReadServerResponse_GetReviews not verifying each review") } if (reviewNetworkType != networkType){ return false, nil } if (len(expectedReviewersList) != 0){ isExpectedReviewer := slices.Contains(expectedReviewersList, authorIdentityHash) if (isExpectedReviewer == false){ return false, nil } } expectedReviewedHash, exists := expectedReviewsInfoMap[reviewHash] if (exists == false) { // We received an unexpected reviewHash return false, nil } areEqual := bytes.Equal(reviewReviewedHash, expectedReviewedHash) if (areEqual == false){ // We received an unexpected reviewedHash for expected reviewHash return false, nil } } return true, nil } responseIsValid, err := checkIfResponseIsValid() if (err != nil) { return false, nil, err } if (responseIsValid == false){ // Peer sent invalid response, must be malicious err := maliciousHosts.AddHostToMaliciousHostsList(hostIdentityHash) if (err != nil) { return false, nil, err } return false, nil, nil } return true, reviewsList, nil } //Outputs: // -bool: Download successful (could be unsuccessful because host keys not found, host is malicious, internet connection down, and more) // -map[[30]byte][]byte: Reports info map (Report Hash -> Reported Hash) // -error func GetIdentityReportsInfoFromHost( connectionIdentifier [21]byte, hostIdentityHash [16]byte, networkType byte, identityTypeToRetrieve string, rangeStart [16]byte, rangeEnd [16]byte, reportedIdentityHashesList [][16]byte)(bool, map[[30]byte][]byte, error){ connectionExists, connectionHostIdentityHash, connectionKey, connectionNetworkType, err := peerClient.GetConnectionMetadata(connectionIdentifier) if (err != nil) { return false, nil, err } if (connectionExists == false){ return false, nil, nil } if (connectionHostIdentityHash != hostIdentityHash){ return false, nil, errors.New("GetIdentityReportsInfoFromHost called with hostIdentityHash which does not match connection metadata.") } if (connectionNetworkType != networkType){ return false, nil, errors.New("GetIdentityReportsInfoFromHost called with networkType which does not match connection metadata.") } acceptableReportVersionsList := []int{1} requestBytes, requestIdentifier, err := serverRequest.CreateServerRequest_GetIdentityReportsInfo(hostIdentityHash, connectionKey, networkType, acceptableReportVersionsList, identityTypeToRetrieve, rangeStart, rangeEnd, reportedIdentityHashesList) if (err != nil) { return false, nil, err } requestSuccessful, responseBytes, err := peerClient.SendRequestThroughConnection(connectionIdentifier, requestBytes) if (err != nil) { return false, nil, err } if (requestSuccessful == false){ return false, nil, nil } ableToRead, requestIdentifier_Received, hostIdentityHash_Received, reportsInfoMap, err := serverResponse.ReadServerResponse_GetIdentityReportsInfo(responseBytes, connectionKey) if (err != nil) { return false, nil, err } if (ableToRead == false){ // Peer sent invalid response, must be malicious err := maliciousHosts.AddHostToMaliciousHostsList(hostIdentityHash) if (err != nil){ return false, nil, err } return false, nil, nil } // Now we check to make sure response is valid based on input request information checkIfResponseIsValid := func()(bool, error){ if (requestIdentifier != requestIdentifier_Received){ // Host sent invalid response, must be malicious return false, nil } if (hostIdentityHash != hostIdentityHash_Received){ // Peer sent invalid response, must be malicious return false, nil } // Now we verify received reports info map fulfills request filters for _, reportedHash := range reportsInfoMap{ // reportedHash is either Profile hash or identity hash or Attribute hash reportedType, err := helpers.GetReportedTypeFromReportedHash(reportedHash) if (err != nil){ reportedHashHex := encoding.EncodeBytesToHexString(reportedHash) return false, errors.New("ReadServerResponse_GetReportsInfo not verifying reportedHash: " + reportedHashHex) } if (reportedType != "Identity" && reportedType != "Profile" && reportedType != "Attribute"){ reportedHashHex := encoding.EncodeBytesToHexString(reportedHash) return false, errors.New("ReadServerResponse_GetReportsInfo not verifying reportedHash: " + reportedHashHex) } if (reportedType == "Identity"){ if (len(reportedHash) != 16){ reportedHashHex := encoding.EncodeBytesToHexString(reportedHash) return false, errors.New("GetReportedTypeFromReportedHash returning Identity for different length reportedHash: " + reportedHashHex) } reportedIdentityHash := [16]byte(reportedHash) if (len(reportedIdentityHashesList) == 0){ identityType, err := identity.GetIdentityTypeFromIdentityHash(reportedIdentityHash) if (err != nil){ reportedIdentityHashHex := encoding.EncodeBytesToHexString(reportedIdentityHash[:]) return false, errors.New("GetReportedTypeFromReportedHash not verifying identityHash: " + reportedIdentityHashHex) } if (identityType != identityTypeToRetrieve){ // We only need to verify identityType if a reportedHashesList was not requested return false, nil } } isWithinRange, err := byteRange.CheckIfIdentityHashIsWithinRange(rangeStart, rangeEnd, reportedIdentityHash) if (err != nil) { return false, err } if (isWithinRange == false){ return false, nil } if (len(reportedIdentityHashesList) != 0){ identityHashIsInRequestedList := slices.Contains(reportedIdentityHashesList, reportedIdentityHash) if (identityHashIsInRequestedList == false){ return false, nil } } continue } if (reportedType == "Profile"){ if (len(reportedHash) != 28){ reportedHashHex := encoding.EncodeBytesToHexString(reportedHash) return false, errors.New("GetReportedTypeFromReportedHash returning Profile for different length reportedHash: " + reportedHashHex) } reportedProfileHash := [28]byte(reportedHash) if (len(reportedIdentityHashesList) == 0){ // We only need to verify profileType if a reportedHashesList was not requested profileType, isDisabled, err := readProfiles.ReadProfileHashMetadata(reportedProfileHash) if (err != nil) { return false, errors.New("GetReportedTypeFromReportedHash not verifying profileHash") } if (isDisabled == true){ return false, errors.New("GetReportedTypeFromReportedHash not verifying profileHash is not disabled.") } if (profileType != identityTypeToRetrieve){ return false, nil } } } } return true, nil } responseIsValid, err := checkIfResponseIsValid() if (err != nil) { return false, nil, err } if (responseIsValid == false){ err := maliciousHosts.AddHostToMaliciousHostsList(hostIdentityHash) if (err != nil){ return false, nil, err } return false, nil, nil } return true, reportsInfoMap, nil } //Outputs: // -bool: Download successful (could be unsuccessful because host keys not found, host is malicious, internet connection down, and more) // -map[[30]byte][26]byte: Reports info map (Report Hash -> Reported Message Hash) // -error func GetMessageReportsInfoFromHost( connectionIdentifier [21]byte, hostIdentityHash [16]byte, networkType byte, rangeStart [10]byte, rangeEnd [10]byte, reportedMessageHashesList [][26]byte)(bool, map[[30]byte][26]byte, error){ connectionExists, connectionHostIdentityHash, connectionKey, connectionNetworkType, err := peerClient.GetConnectionMetadata(connectionIdentifier) if (err != nil) { return false, nil, err } if (connectionExists == false){ return false, nil, nil } if (connectionHostIdentityHash != hostIdentityHash){ return false, nil, errors.New("GetMessageReportsInfoFromHost called with hostIdentityHash which does not match connection metadata.") } if (connectionNetworkType != networkType){ return false, nil, errors.New("GetMessageReportsInfoFromHost called with networkType which does not match connection metadata.") } acceptableReportVersionsList := []int{1} requestBytes, requestIdentifier, err := serverRequest.CreateServerRequest_GetMessageReportsInfo(hostIdentityHash, connectionKey, networkType, acceptableReportVersionsList, rangeStart, rangeEnd, reportedMessageHashesList) if (err != nil) { return false, nil, err } requestSuccessful, responseBytes, err := peerClient.SendRequestThroughConnection(connectionIdentifier, requestBytes) if (err != nil) { return false, nil, err } if (requestSuccessful == false){ return false, nil, nil } ableToRead, requestIdentifier_Received, hostIdentityHash_Received, reportsInfoMap, err := serverResponse.ReadServerResponse_GetMessageReportsInfo(responseBytes, connectionKey) if (err != nil) { return false, nil, err } if (ableToRead == false){ // Peer sent invalid response, must be malicious err := maliciousHosts.AddHostToMaliciousHostsList(hostIdentityHash) if (err != nil){ return false, nil, err } return false, nil, nil } // Now we check to make sure response is valid based on input request information checkIfResponseIsValid := func()(bool, error){ if (requestIdentifier != requestIdentifier_Received){ // Host sent invalid response, must be malicious return false, nil } if (hostIdentityHash != hostIdentityHash_Received){ // Peer sent invalid response, must be malicious return false, nil } // Now we verify received reports info map fulfills request filters for _, reportedHash := range reportsInfoMap{ // reportedHash is a message hash if (len(reportedMessageHashesList) != 0){ messageHashIsInRequestedList := slices.Contains(reportedMessageHashesList, reportedHash) if (messageHashIsInRequestedList == false){ return false, nil } } } return true, nil } responseIsValid, err := checkIfResponseIsValid() if (err != nil) { return false, nil, err } if (responseIsValid == false){ err := maliciousHosts.AddHostToMaliciousHostsList(hostIdentityHash) if (err != nil){ return false, nil, err } return false, nil, nil } return true, reportsInfoMap, nil } //Outputs: // -bool: Download successful (could be unsuccessful because host keys not found, host is malicious, internet connection down, and more) // -[][]byte: Retrieved list of reports // -error func GetReportsFromHost( connectionIdentifier [21]byte, hostIdentityHash [16]byte, networkType byte, reportHashesList [][30]byte, expectedReportsInfoMap map[[30]byte][]byte)(bool, [][]byte, error){ connectionExists, connectionHostIdentityHash, connectionKey, connectionNetworkType, err := peerClient.GetConnectionMetadata(connectionIdentifier) if (err != nil) { return false, nil, err } if (connectionExists == false){ return false, nil, nil } if (connectionHostIdentityHash != hostIdentityHash){ return false, nil, errors.New("GetReportsFromHost called with hostIdentityHash which does not match connection metadata.") } if (connectionNetworkType != networkType){ return false, nil, errors.New("GetReportsFromHost called with networkType which does not match connection metadata.") } requestBytes, requestIdentifier, err := serverRequest.CreateServerRequest_GetReports(hostIdentityHash, connectionKey, networkType, reportHashesList) if (err != nil) { return false, nil, err } requestSuccessful, responseData, err := peerClient.SendRequestThroughConnection(connectionIdentifier, requestBytes) if (err != nil) { return false, nil, err } if (requestSuccessful == false){ return false, nil, nil } ableToRead, requestIdentifier_Received, hostIdentityHash_Received, reportsList, err := serverResponse.ReadServerResponse_GetReports(responseData, connectionKey) if (err != nil) { return false, nil, err } if (ableToRead == false){ // Peer sent invalid response, must be malicious err := maliciousHosts.AddHostToMaliciousHostsList(hostIdentityHash) if (err != nil) { return false, nil, err } return false, nil, nil } // Now we check to make sure response is valid based on input request information checkIfResponseIsValid := func()(bool, error){ if (requestIdentifier != requestIdentifier_Received){ // Host sent invalid response, must be malicious return false, nil } if (hostIdentityHash != hostIdentityHash_Received){ return false, nil } for _, reportBytes := range reportsList{ ableToRead, reportHash, _, reportNetworkType, _, _, reportReportedHash, _, err := readReports.ReadReportAndHash(false, reportBytes) if (err != nil) { return false, err } if (ableToRead == false){ // Report is invalid, peer must be malicious. return false, nil } if (reportNetworkType != networkType){ return false, nil } expectedReportedHash, exists := expectedReportsInfoMap[reportHash] if (exists == false) { // We received an unexpected reportHash return false, nil } areEqual := bytes.Equal(reportReportedHash, expectedReportedHash) if (areEqual == false){ // We received an unexpected reportedHash for expected reportHash return false, nil } } return true, nil } responseIsValid, err := checkIfResponseIsValid() if (err != nil) { return false, nil, err } if (responseIsValid == false){ // Peer sent invalid response, must be malicious err := maliciousHosts.AddHostToMaliciousHostsList(hostIdentityHash) if (err != nil) { return false, nil, err } return false, nil, nil } return true, reportsList, nil } //Outputs: // -bool: Successful download // -[]serverResponse.DepositStruct // -[]string: List of addresses with no deposits // -error func GetAddressDepositsFromHost( connectionIdentifier [21]byte, hostIdentityHash [16]byte, networkType byte, cryptocurrency string, cryptoAddressesList []string)(bool, []serverResponse.DepositStruct, []string, error){ connectionExists, connectionHostIdentityHash, connectionKey, connectionNetworkType, err := peerClient.GetConnectionMetadata(connectionIdentifier) if (err != nil) { return false, nil, nil, err } if (connectionExists == false){ return false, nil, nil, nil } if (connectionHostIdentityHash != hostIdentityHash){ return false, nil, nil, errors.New("GetAddressDepositsFromHost called with hostIdentityHash which does not match connection metadata.") } if (connectionNetworkType != networkType){ return false, nil, nil, errors.New("GetAddressDepositsFromHost called with networkType which does not match connection metadata.") } requestBytes, requestIdentifier, err := serverRequest.CreateServerRequest_GetAddressDeposits(hostIdentityHash, connectionKey, networkType, cryptocurrency, cryptoAddressesList) if (err != nil) { return false, nil, nil, err } requestSuccessful, responseData, err := peerClient.SendRequestThroughConnection(connectionIdentifier, requestBytes) if (err != nil) { return false, nil, nil, err } if (requestSuccessful == false){ return false, nil, nil, nil } ableToRead, requestIdentifier_Received, hostIdentityHash_Received, addressDepositObjectsList, err := serverResponse.ReadServerResponse_GetAddressDeposits(responseData, connectionKey) if (err != nil) { return false, nil, nil, err } if (ableToRead == false){ // Peer sent invalid response, must be malicious err := maliciousHosts.AddHostToMaliciousHostsList(hostIdentityHash) if (err != nil) { return false, nil, nil, err } return false, nil, nil, nil } // Now we check to make sure response is valid based on input request information // This map will store all addresses which have deposits addressesWithDepositsMap := make(map[string]struct{}) checkIfResponseIsValid := func()(bool, error){ if (requestIdentifier != requestIdentifier_Received){ // Host sent invalid response, must be malicious return false, nil } if (hostIdentityHash != hostIdentityHash_Received){ return false, nil } for _, depositObject := range addressDepositObjectsList{ depositAddress := depositObject.Address addressExists := slices.Contains(cryptoAddressesList, depositAddress) if (addressExists == false){ return false, nil } addressesWithDepositsMap[depositAddress] = struct{}{} } return true, nil } responseIsValid, err := checkIfResponseIsValid() if (err != nil) { return false, nil, nil, err } if (responseIsValid == false){ // Host sent invalid response, they must be malicious err := maliciousHosts.AddHostToMaliciousHostsList(hostIdentityHash) if (err != nil) { return false, nil, nil, err } return false, nil, nil, nil } addressesWithoutDepositsList := make([]string, 0) for _, cryptoAddress := range cryptoAddressesList{ _, exists := addressesWithDepositsMap[cryptoAddress] if (exists == false){ addressesWithoutDepositsList = append(addressesWithoutDepositsList, cryptoAddress) } } return true, addressDepositObjectsList, addressesWithoutDepositsList, nil } //Inputs: // -[21]byte: Connection Identifier // -[16]byte: Host Identity Hash // -byte: Network Type // -[][16]byte: Identity hashes to retrieve viewable statuses for // -[][28]byte: Profiles hashes to retrieve viewable statuses for //Outputs: // -bool: Successful download // -map[[16]byte]bool: Identity Hash Statuses Map (Identity Hash -> true/false) (true = viewable, false = unviewable) // -map[[28]byte]bool: Profile Hash Statuses Map (Profile Hash -> true/false) (true = viewable, false = unviewable) // -error func GetViewableStatusesFromHost( connectionIdentifier [21]byte, hostIdentityHash [16]byte, networkType byte, identityHashesList [][16]byte, profileHashesList [][28]byte)(bool, map[[16]byte]bool, map[[28]byte]bool, error){ connectionExists, connectionHostIdentityHash, connectionKey, connectionNetworkType, err := peerClient.GetConnectionMetadata(connectionIdentifier) if (err != nil) { return false, nil, nil, err } if (connectionExists == false){ return false, nil, nil, nil } if (connectionHostIdentityHash != hostIdentityHash){ return false, nil, nil, errors.New("GetViewableStatusesFromHost called with hostIdentityHash which does not match connection metadata.") } if (connectionNetworkType != networkType){ return false, nil, nil, errors.New("GetViewableStatusesFromHost called with networkType which does not match connection metadata.") } requestBytes, requestIdentifier, err := serverRequest.CreateServerRequest_GetViewableStatuses(hostIdentityHash, connectionKey, networkType, identityHashesList, profileHashesList) if (err != nil) { return false, nil, nil, err } requestSuccessful, responseData, err := peerClient.SendRequestThroughConnection(connectionIdentifier, requestBytes) if (err != nil) { return false, nil, nil, err } if (requestSuccessful == false){ return false, nil, nil, nil } ableToRead, requestIdentifier_Received, hostIdentityHash_Received, identityHashStatusesMap, profileHashStatusesMap, err := serverResponse.ReadServerResponse_GetViewableStatuses(responseData, connectionKey) if (err != nil) { return false, nil, nil, err } if (ableToRead == false){ // Peer sent invalid response, must be malicious err := maliciousHosts.AddHostToMaliciousHostsList(hostIdentityHash) if (err != nil) { return false, nil, nil, err } return false, nil, nil, nil } // Now we check to make sure response is valid based on input request information checkIfResponseIsValid := func()(bool, error){ if (requestIdentifier != requestIdentifier_Received){ // Host sent invalid response, must be malicious return false, nil } if (hostIdentityHash != hostIdentityHash_Received){ return false, nil } for identityHash, _ := range identityHashStatusesMap{ isRequestedIdentityHash := slices.Contains(identityHashesList, identityHash) if (isRequestedIdentityHash == false){ return false, nil } } for profileHash, _ := range profileHashStatusesMap{ isRequestedProfileHash := slices.Contains(profileHashesList, profileHash) if (isRequestedProfileHash == false){ return false, nil } } return true, nil } responseIsValid, err := checkIfResponseIsValid() if (err != nil) { return false, nil, nil, err } if (responseIsValid == false){ // Peer sent invalid response, must be malicious err := maliciousHosts.AddHostToMaliciousHostsList(hostIdentityHash) if (err != nil) { return false, nil, nil, err } return false, nil, nil, nil } return true, identityHashStatusesMap, profileHashStatusesMap, nil } //Inputs: // -[21]byte: Connection Identifier // -[16]byte: Host Identity Hash // -byte: Network Type // -string: Content Type ("Profile"/"Message"/"Review"/"Report"/"Parameters") // -[][]byte: Contents list //Outputs: // -bool: Successful download // -map[string]bool: Received Content Accepted Info Map (Content Hash -> true/false) // -error func BroadcastContentToHost( connectionIdentifier [21]byte, hostIdentityHash [16]byte, networkType byte, contentType string, contentList [][]byte)(bool, map[string]bool, error){ connectionExists, connectionHostIdentityHash, connectionKey, connectionNetworkType, err := peerClient.GetConnectionMetadata(connectionIdentifier) if (err != nil) { return false, nil, err } if (connectionExists == false){ return false, nil, nil } if (connectionHostIdentityHash != hostIdentityHash){ return false, nil, errors.New("BroadcastContentToHost called with hostIdentityHash which does not match connection metadata.") } if (connectionNetworkType != networkType){ return false, nil, errors.New("BroadcastContentToHost called with networkType which does not match connection metadata.") } requestBytes, requestIdentifier, err := serverRequest.CreateServerRequest_BroadcastContent(hostIdentityHash, connectionKey, networkType, contentType, contentList) if (err != nil) { return false, nil, err } requestSuccessful, responseData, err := peerClient.SendRequestThroughConnection(connectionIdentifier, requestBytes) if (err != nil) { return false, nil, err } if (requestSuccessful == false){ return false, nil, nil } ableToRead, requestIdentifier_Received, hostIdentityHash_Received, contentAcceptedInfoMap, err := serverResponse.ReadServerResponse_BroadcastContent(responseData, connectionKey) if (err != nil) { return false, nil, err } if (ableToRead == false){ // Peer sent invalid response, must be malicious err := maliciousHosts.AddHostToMaliciousHostsList(hostIdentityHash) if (err != nil) { return false, nil, err } return false, nil, nil } // Now we check to make sure response is valid based on input request information checkIfResponseIsValid := func()(bool, error){ if (requestIdentifier != requestIdentifier_Received){ // Host sent invalid response, must be malicious return false, nil } if (hostIdentityHash != hostIdentityHash_Received){ return false, nil } for _, contentBytes := range contentList{ ableToRead, contentHash, err := readContent.GetContentHashFromContentBytes(false, contentType, contentBytes) if (err != nil) { return false, err } if (ableToRead == false){ return false, errors.New("CreateServerRequest_BroadcastContent not verifying content is valid.") } _, exists := contentAcceptedInfoMap[string(contentHash)] if (exists == false){ // Host did not tell us if they accepted the content // Host is malicious return false, nil } } return true, nil } responseIsValid, err := checkIfResponseIsValid() if (err != nil) { return false, nil, err } if (responseIsValid == false){ // Peer sent invalid response, must be malicious err := maliciousHosts.AddHostToMaliciousHostsList(hostIdentityHash) if (err != nil) { return false, nil, err } return false, nil, nil } return true, contentAcceptedInfoMap, nil }