mirror of https://github.com/oxen-io/session-ios
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
87 lines
3.2 KiB
Swift
87 lines
3.2 KiB
Swift
2 years ago
|
// Copyright © 2023 Rangeproof Pty Ltd. All rights reserved.
|
||
|
|
||
|
import Foundation
|
||
|
import Sodium
|
||
|
|
||
|
internal protocol ValidatableResponse {
|
||
|
associatedtype ValidationData
|
||
|
associatedtype ValidationResponse
|
||
|
|
||
|
/// This valid controls the number of successful responses for a response to be considered "valid", a
|
||
|
/// positive number indicates an exact number of responses required whereas a negative number indicates
|
||
|
/// a dividing factor, eg.
|
||
|
/// 2 = Two nodes need to have returned success responses
|
||
|
/// -2 = 50% of the nodes need to have returned success responses
|
||
|
/// -4 = 25% of the nodes need to have returned success responses
|
||
|
static var requiredSuccessfulResponses: Int { get }
|
||
|
|
||
|
static func validated(
|
||
|
map validResultMap: [String: ValidationResponse],
|
||
|
totalResponseCount: Int
|
||
|
) throws -> [String: ValidationResponse]
|
||
|
|
||
|
func validResultMap(
|
||
|
sodium: Sodium,
|
||
|
userX25519PublicKey: String,
|
||
|
validationData: ValidationData
|
||
|
) throws -> [String: ValidationResponse]
|
||
|
|
||
|
func validateResultMap(sodium: Sodium, userX25519PublicKey: String, validationData: ValidationData) throws
|
||
|
}
|
||
|
|
||
|
// MARK: - Convenience
|
||
|
|
||
|
internal extension ValidatableResponse {
|
||
|
func validateResultMap(sodium: Sodium, userX25519PublicKey: String, validationData: ValidationData) throws {
|
||
|
_ = try validResultMap(
|
||
|
sodium: sodium,
|
||
|
userX25519PublicKey: userX25519PublicKey,
|
||
|
validationData: validationData
|
||
|
)
|
||
|
}
|
||
|
|
||
|
static func validated(
|
||
|
map validResultMap: [String: ValidationResponse],
|
||
|
totalResponseCount: Int
|
||
|
) throws -> [String: ValidationResponse] {
|
||
|
let numSuccessResponses: Int = validResultMap.count
|
||
|
let successPercentage: CGFloat = (CGFloat(numSuccessResponses) / CGFloat(totalResponseCount))
|
||
|
|
||
|
guard
|
||
|
( // Positive value is an exact number comparison
|
||
|
Self.requiredSuccessfulResponses >= 0 &&
|
||
|
numSuccessResponses >= Self.requiredSuccessfulResponses
|
||
|
) || (
|
||
|
// Negative value is a "divisor" for a percentage comparison
|
||
|
Self.requiredSuccessfulResponses < 0 &&
|
||
|
successPercentage >= abs(1 / CGFloat(Self.requiredSuccessfulResponses))
|
||
|
)
|
||
|
else { throw SnodeAPIError.responseFailedValidation }
|
||
|
|
||
|
return validResultMap
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal extension ValidatableResponse where ValidationData == Void {
|
||
|
func validResultMap(sodium: Sodium, userX25519PublicKey: String) throws -> [String: ValidationResponse] {
|
||
|
return try validResultMap(sodium: sodium, userX25519PublicKey: userX25519PublicKey, validationData: ())
|
||
|
}
|
||
|
|
||
|
func validateResultMap(sodium: Sodium, userX25519PublicKey: String) throws {
|
||
|
_ = try validResultMap(
|
||
|
sodium: sodium,
|
||
|
userX25519PublicKey: userX25519PublicKey,
|
||
|
validationData: ()
|
||
|
)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal extension ValidatableResponse where ValidationResponse == Bool {
|
||
|
static func validated(map validResultMap: [String: Bool]) throws -> [String: Bool] {
|
||
|
return try validated(
|
||
|
map: validResultMap.filter { $0.value },
|
||
|
totalResponseCount: validResultMap.count
|
||
|
)
|
||
|
}
|
||
|
}
|