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.
		
		
		
		
		
			
		
			
				
	
	
		
			37 lines
		
	
	
		
			1.5 KiB
		
	
	
	
		
			Swift
		
	
			
		
		
	
	
			37 lines
		
	
	
		
			1.5 KiB
		
	
	
	
		
			Swift
		
	
| import SessionSnodeKit
 | |
| import SessionUtilitiesKit
 | |
| 
 | |
| enum ProofOfWork {
 | |
| 
 | |
|     /// A modified version of [Bitmessage's Proof of Work Implementation](https://bitmessage.org/wiki/Proof_of_work).
 | |
|     static func calculate(ttl: UInt64, publicKey: String, data: String) -> (timestamp: UInt64, base64EncodedNonce: String)? {
 | |
|         let nonceSize = MemoryLayout<UInt64>.size
 | |
|         // Get millisecond timestamp
 | |
|         let timestamp = NSDate.millisecondTimestamp()
 | |
|         // Construct payload
 | |
|         let payloadAsString = String(timestamp) + String(ttl) + publicKey + data
 | |
|         let payload = payloadAsString.bytes
 | |
|         // Calculate target
 | |
|         let numerator = UInt64.max
 | |
|         let difficulty = UInt64(1)
 | |
|         let totalSize = UInt64(payload.count + nonceSize)
 | |
|         let ttlInSeconds = ttl / 1000
 | |
|         let denominator = difficulty * (totalSize + (ttlInSeconds * totalSize) / UInt64(UInt16.max))
 | |
|         let target = numerator / denominator
 | |
|         // Calculate proof of work
 | |
|         var value = UInt64.max
 | |
|         let payloadHash = payload.sha512()
 | |
|         var nonce = UInt64(0)
 | |
|         while value > target {
 | |
|             nonce = nonce &+ 1
 | |
|             let hash = (nonce.bigEndianBytes + payloadHash).sha512()
 | |
|             guard let newValue = UInt64(fromBigEndianBytes: [UInt8](hash[0..<nonceSize])) else { return nil }
 | |
|             value = newValue
 | |
|         }
 | |
|         // Encode as base 64
 | |
|         let base64EncodedNonce = nonce.bigEndianBytes.toBase64()!
 | |
|         // Return
 | |
|         return (timestamp, base64EncodedNonce)
 | |
|     }
 | |
| }
 |