[Merge] Proof of Work

pull/5/head
Niels Andriesse 6 years ago committed by GitHub
commit 3ce721f069
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,131 @@
import CryptoSwift
private extension UInt64 {
init(_ decimal: Decimal) {
self.init(truncating: decimal as NSDecimalNumber)
}
}
// UInt8 Array specific stuff we need
private extension Array where Element == UInt8 {
// Convert a UInt64 into an array of size 8
init(_ uint64: UInt64) {
let array = stride(from: 0, to: 64, by: 8).reversed().map {
UInt8(uint64 >> $0 & 0x000000FF)
}
self.init(array)
}
/// Compare if lhs array is greater than rhs array
static func >(lhs: [UInt8], rhs: [UInt8]) -> Bool {
guard lhs.count == rhs.count else { return false }
for i in (0..<lhs.count) {
// If the values are the same then move onto the next pair
if (lhs[i] == rhs[i]) { continue }
return lhs[i] > rhs[i]
}
return false
}
/// Increment the UInt8 array by a given amount
///
/// - Parameter amount: The amount to increment by
/// - Returns: The incrememnted array
func increment(by amount: Int) -> [UInt8] {
var newNonce = self
var increment = amount
for i in (0..<newNonce.count).reversed() {
guard increment > 0 else { break }
let sum = Int(newNonce[i]) + increment
newNonce[i] = UInt8(sum % 256)
increment = sum / 256
}
return newNonce
}
}
/**
* The main logic which handles proof of work.
*
* This was copied from the messenger desktop.
* Ref: libloki/proof-of-work.js
*/
public enum ProofOfWork {
// If this changes then we also have to use something other than UInt64 to support the new length
private static let nonceLength = 8
// Modify this value for difficulty scaling
private enum NonceTrials {
static let development = 10
static let production = 100
}
struct Configuration {
var pubKey: String
var data: String
var timestamp: Date
var ttl: Int
var isDevelopment = false
var payload: [UInt8] {
let timestampString = String(Int(timestamp.timeIntervalSince1970))
let ttlString = String(ttl)
let payloadString = timestampString + ttlString + pubKey + data
return payloadString.bytes
}
}
/// Calculate a proof of work for the given configuration
///
/// Ref: https://bitmessage.org/wiki/Proof_of_work
///
/// - Parameter config: The configuration data
/// - Returns: A nonce string or nil if it failed
static func calculate(with config: Configuration) -> String? {
let payload = config.payload
let nonceTrials = config.isDevelopment ? NonceTrials.development : NonceTrials.production
let target = calcTarget(ttl: config.ttl, payloadLength: payload.count, nonceTrials: nonceTrials)
// Start with most the max value we can
var trialValue = [UInt8](repeating: UInt8.max, count: nonceLength)
let initialHash = payload.sha512()
var nonce = [UInt8](repeating: 0, count: nonceLength)
while trialValue > target {
nonce = nonce.increment(by: 1)
// This is different to the bitmessage pow
// resultHash = hash(nonce + hash(data)) ==> hash(nonce + initialHash)
let resultHash = (nonce + initialHash).sha512()
trialValue = Array(resultHash[0..<8])
}
return nonce.toBase64()
}
/// Calculate the UInt8 target we need to reach
private static func calcTarget(ttl: Int, payloadLength: Int, nonceTrials: Int) -> [UInt8] {
let two16 = UInt64(pow(2, 16) - 1)
let two64 = UInt64(pow(2, 64) - 1)
// ttl converted to seconds
let ttlSeconds = ttl / 1000
// Do all the calculations
let totalLength = UInt64(payloadLength + nonceLength)
let ttlMult = UInt64(ttlSeconds) * totalLength
// UInt64 values
let innerFrac = ttlMult / two16
let lenPlusInnerFrac = totalLength + innerFrac
let denominator = UInt64(nonceTrials) * lenPlusInnerFrac
let targetNum = two64 / denominator
return [UInt8](targetNum)
}
}

@ -1 +1 @@
Subproject commit aed207f026696cbb76066748fba6689a9c04194e
Subproject commit 34ae9f4f2dd47c4d66de7525fbe1054f4f573512

@ -7,6 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
242D3F4B227966A30035F945 /* ProofOfWork.swift in Sources */ = {isa = PBXBuildFile; fileRef = 242D3F4A227966A20035F945 /* ProofOfWork.swift */; };
2AE2882E4C2B96BFFF9EE27C /* Pods_SignalShareExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0F94C85CB0B235DA37F68ED0 /* Pods_SignalShareExtension.framework */; };
3403B95D20EA9527001A1F44 /* OWSContactShareButtonsView.m in Sources */ = {isa = PBXBuildFile; fileRef = 3403B95B20EA9526001A1F44 /* OWSContactShareButtonsView.m */; };
34074F61203D0CBE004596AE /* OWSSounds.m in Sources */ = {isa = PBXBuildFile; fileRef = 34074F5F203D0CBD004596AE /* OWSSounds.m */; };
@ -659,6 +660,7 @@
0F94C85CB0B235DA37F68ED0 /* Pods_SignalShareExtension.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SignalShareExtension.framework; sourceTree = BUILT_PRODUCTS_DIR; };
1C93CF3971B64E8B6C1F9AC1 /* Pods-SignalShareExtension.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SignalShareExtension.test.xcconfig"; path = "Pods/Target Support Files/Pods-SignalShareExtension/Pods-SignalShareExtension.test.xcconfig"; sourceTree = "<group>"; };
1CE3CD5C23334683BDD3D78C /* Pods-Signal.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Signal.test.xcconfig"; path = "Pods/Target Support Files/Pods-Signal/Pods-Signal.test.xcconfig"; sourceTree = "<group>"; };
242D3F4A227966A20035F945 /* ProofOfWork.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProofOfWork.swift; sourceTree = "<group>"; };
264242150E87D10A357DB07B /* Pods_SignalMessaging.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SignalMessaging.framework; sourceTree = BUILT_PRODUCTS_DIR; };
3403B95B20EA9526001A1F44 /* OWSContactShareButtonsView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSContactShareButtonsView.m; sourceTree = "<group>"; };
3403B95C20EA9527001A1F44 /* OWSContactShareButtonsView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSContactShareButtonsView.h; sourceTree = "<group>"; };
@ -2618,6 +2620,7 @@
B8DC3D7522795E2300D909D6 /* ECKeyPair.m */,
B8DC3D7422795E2300D909D6 /* ECKeyPair.swift */,
B8DC3D7622795E2400D909D6 /* LokiMessagingAPI.swift */,
242D3F4A227966A20035F945 /* ProofOfWork.swift */,
);
path = LokiKit;
sourceTree = "<group>";
@ -3641,6 +3644,7 @@
34D2CCE0206939B400CB1A14 /* DebugUIMessagesAssetLoader.m in Sources */,
4CEB78C92178EBAB00F315D2 /* OWSSessionResetJobRecord.m in Sources */,
45794E861E00620000066731 /* CallUIAdapter.swift in Sources */,
242D3F4B227966A30035F945 /* ProofOfWork.swift in Sources */,
340FC8BA204DAC8D007AEB0F /* FingerprintViewScanController.m in Sources */,
4585C4681ED8F8D200896AEA /* SafetyNumberConfirmationAlert.swift in Sources */,
4C20B2B920CA10DE001BAC90 /* ConversationSearchViewController.swift in Sources */,

Loading…
Cancel
Save