Made ProofOfWork work in objective c.

Added proof of work calculation when sending message.
pull/6/head
Mikunj 6 years ago
parent de01731316
commit ad0fc7944e

@ -43,7 +43,8 @@ private extension MutableCollection where Element == UInt8, Index == Int {
* This was copied from the desktop messenger.
* Ref: libloki/proof-of-work.js
*/
public enum ProofOfWork {
@objc public class ProofOfWork: NSObject {
private override init() {}
// If this changes then we also have to use something other than UInt64 to support the new length
private static let nonceLength = 8
@ -55,36 +56,19 @@ public enum ProofOfWork {
}
}()
public struct Configuration {
var pubKey: String
var data: String
var timestamp: Date
var ttl: Int
var payload: [UInt8] {
let timestampString = String(Int(timestamp.timeIntervalSince1970))
let ttlString = String(ttl)
let payloadString = timestampString + ttlString + pubKey + data
return payloadString.bytes
}
public init(pubKey: String, data: String, timestamp: Date, ttl: Int) {
self.pubKey = pubKey
self.data = data
self.timestamp = timestamp
self.ttl = ttl
}
}
/// Calculate a proof of work with the given configuration
///
/// Ref: https://bitmessage.org/wiki/Proof_of_work
///
/// - Parameter config: The configuration
/// - Parameters:
/// - data: The message data
/// - pubKey: The message recipient
/// - timestamp: The timestamp
/// - ttl: The message time to live
/// - Returns: A nonce string or nil if it failed
public static func calculate(with config: Configuration) -> String? {
let payload = config.payload
let target = calcTarget(ttl: config.ttl, payloadLength: payload.count, nonceTrials: nonceTrialCount)
@objc public class func calculate(forData data: String, pubKey: String, timestamp: UInt64, ttl: Int) -> String? {
let payload = getPayload(pubKey: pubKey, data: data, timestamp: timestamp, ttl: ttl)
let target = calcTarget(ttl: ttl, payloadLength: payload.count, nonceTrials: nonceTrialCount)
// Start with the max value
var trialValue = UInt64.max
@ -105,8 +89,16 @@ public enum ProofOfWork {
return nonce.toBase64()
}
/// Get the proof of work payload
private class func getPayload(pubKey: String, data: String, timestamp: UInt64, ttl: Int) -> [UInt8] {
let timestampString = String(timestamp)
let ttlString = String(ttl)
let payloadString = timestampString + ttlString + pubKey + data
return payloadString.bytes
}
/// Calculate the target we need to reach
private static func calcTarget(ttl: Int, payloadLength: Int, nonceTrials: Int) -> UInt64 {
private class func calcTarget(ttl: Int, payloadLength: Int, nonceTrials: Int) -> UInt64 {
let two16 = UInt64(pow(2, 16) - 1)
let two64 = UInt64(pow(2, 64) - 1)

@ -915,6 +915,38 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
return deviceMessages;
}
- (AnyPromise *)calculateProofOfWorkForDeviceMessages:(NSArray<NSDictionary *> *)deviceMessages
ttl:(NSNumber *)ttl
{
// LOKI: Calculate the proof of work for each device message
NSMutableArray *promises = [[NSMutableArray alloc] init];
for (NSDictionary<NSString *, id> *deviceMessage in deviceMessages) {
AnyPromise *promise = [AnyPromise promiseWithValue:deviceMessage]
.thenOn(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(NSDictionary<NSString *, id> *message) {
NSTimeInterval timestampInterval = [[NSDate date] timeIntervalSince1970];
NSNumber *timestamp = [NSNumber numberWithDouble:timestampInterval];
NSString *destination = message[@"destination"];
NSString *data = message[@"content"];
NSString *_Nullable nonce = [ProofOfWork calculateForData:data pubKey:destination timestamp:timestamp.unsignedIntegerValue ttl:ttl.integerValue];
// Return our timestamp along with the nonce
// These will help us identify which nonce belongs to which message
return @{
@"destination": destination,
@"deviceId": message[@"destinationDeviceId"],
@"timestamp": timestamp,
@"nonce": nonce
};
});
[promises addObject:promise];
}
// Wait for all the PoW Calculations to finish
return PMKWhen(promises);
}
- (void)sendMessageToRecipient:(OWSMessageSend *)messageSend
{
OWSAssertDebug(messageSend);
@ -1088,12 +1120,26 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
OWSLogWarn(@"Sending a message with no device messages.");
}
// TODO: Update message here to show the pow cog icon
// LOKI: Calculate the proof of work for each device message
NSNumber *ttl = [NSNumber numberWithInteger:@(4 * 24 * 60 * 60)];
AnyPromise *PoWPromise = [self calculateProofOfWorkForDeviceMessages:deviceMessages ttl:ttl];
[PoWPromise
.thenOn([OWSDispatch sendingQueue], ^(NSArray *nonceArray) {
OWSRequestMaker *requestMaker = [[OWSRequestMaker alloc] initWithLabel:@"Message Send"
requestFactoryBlock:^(SMKUDAccessKey *_Nullable udAccessKey) {
// Loki Changes:
return [OWSRequestFactory submitLokiMessageRequestWithRecipient:recipient.recipientId
messages:deviceMessages
nonceArray:nonceArray
ttl:ttl];
/* Original Code:
return [OWSRequestFactory submitMessageRequestWithRecipient:recipient.recipientId
messages:deviceMessages
timeStamp:message.timestamp
udAccessKey:udAccessKey];
*/
}
udAuthFailureBlock:^{
// Note the UD auth failure so subsequent retries
@ -1108,8 +1154,11 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
recipientId:recipient.recipientId
udAccess:messageSend.udAccess
canFailoverUDAuth:NO];
[[requestMaker makeRequestObjc]
.then(^(OWSRequestMakerResult *result) {
return requestMaker;
})
.thenOn([OWSDispatch sendingQueue], ^(OWSRequestMaker *requestMaker) {
return [requestMaker makeRequestObjc];
}).then(^(OWSRequestMakerResult *result) {
dispatch_async([OWSDispatch sendingQueue], ^{
[self messageSendDidSucceed:messageSend
deviceMessages:deviceMessages

@ -59,6 +59,11 @@ typedef NS_ENUM(NSUInteger, TSVerificationTransport) { TSVerificationTransportVo
captchaToken:(nullable NSString *)captchaToken
transport:(TSVerificationTransport)transport;
+ (TSRequest *)submitLokiMessageRequestWithRecipient:(NSString *)recipientId
messages:(NSArray *)messages
nonceArray:(NSArray *)nonceArray
ttl: (NSNumber *)ttl;
+ (TSRequest *)submitMessageRequestWithRecipient:(NSString *)recipientId
messages:(NSArray *)messages
timeStamp:(uint64_t)timeStamp

@ -354,6 +354,58 @@ NS_ASSUME_NONNULL_BEGIN
return [accountAttributes copy];
}
// LOKI: Convert Signal JSON messages to Loki messages
+ (NSDictionary *)lokiMessagesFromMessages:(NSArray *)messages
nonceArray:(NSArray *)nonceArray
ttl:(NSNumber *)ttl {
NSMutableArray *modifiedMessages = [[NSMutableArray alloc] init];
for (NSDictionary *message in messages) {
NSMutableDictionary *lokiMessage = [[NSMutableDictionary alloc] init];
// Params for our message server
lokiMessage[@"pubKey"] = message[@"destination"];
lokiMessage[@"data"] = message[@"content"];
lokiMessage[@"ttl"] = ttl;
NSDictionary *_Nullable nonce = [self getNonceFromArray:nonceArray forMessage:message];
if (nonce) {
lokiMessage[@"timestamp"] = nonce[@"timestmap"];
lokiMessage[@"nonce"] = nonce[@"nonce"];
}
[modifiedMessages addObject:lokiMessage];
}
return modifiedMessages;
}
+ (NSDictionary *_Nullable)getNonceFromArray:(NSArray *)nonceArray forMessage:(NSDictionary *)message {
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"destination == %@ AND deviceId == %d", message[@"destination"], message[@"destinationDeviceId"]];
NSArray *filtered = [nonceArray filteredArrayUsingPredicate:predicate];
return filtered.count > 0 ? [filtered objectAtIndex:0] : nil;
}
// LOKI: This is the function below with our changes
+ (TSRequest *)submitLokiMessageRequestWithRecipient:(NSString *)recipientId
messages:(NSArray *)messages
nonceArray:(NSArray *)nonceArray
ttl: (NSNumber *)ttl
{
// NOTE: messages may be empty; See comments in OWSDeviceManager.
OWSAssertDebug(recipientId.length > 0);
NSDictionary *lokiMessages = [self lokiMessagesFromMessages:messages nonceArray:nonceArray ttl:ttl];
NSString *path = [textSecureMessagesAPI stringByAppendingString:recipientId];
NSDictionary *parameters = @{
@"messages" : lokiMessages,
};
TSRequest *request = [TSRequest requestWithUrl:[NSURL URLWithString:path] method:@"PUT" parameters:parameters];
return request;
}
+ (TSRequest *)submitMessageRequestWithRecipient:(NSString *)recipientId
messages:(NSArray *)messages
timeStamp:(uint64_t)timeStamp

Loading…
Cancel
Save