I need some insights into what is using memory while the program mines a transaction in this code
import Foundation
import CryptoKit
struct Blockchain {
private var difficulty: Int
var chain: [Transaction]
init(_ difficulty: Int) {
self.difficulty = difficulty
chain = []
}
func isValidChain() -> Bool {
var prevHash: String? = nil
for transaction in chain {
let metadata = transaction.metadata
if transaction.id != 0 {
if metadata.prevHash != prevHash {
return false
}
}
if let derSignature = transaction.senderSignature {
if let signature = try? P256.Signing.ECDSASignature(derRepresentation: derSignature),
let publicKey = try? P256.Signing.PublicKey(derRepresentation: metadata.from),
let encoded = try? JSONEncoder().encode(metadata) {
if !publicKey.isValidSignature(signature, for: encoded){
return false
}
} else {
return false
}
} else {
return false
}
prevHash = calculateHash(transaction)
if let hash = prevHash {
if !hash.hasPrefix(String(repeating: "0", count: difficulty)) {
return false
}
}
}
return true
}
mutating func createTransaction(
to: Data,
privateKey: P256.Signing.PrivateKey,
value: Double
) {
var prevHash: String? = nil
if let prevTransaction = chain.last {
prevHash = calculateHash(prevTransaction)
}
let metadata = Transaction.Metadata(
prevHash: prevHash,
from: privateKey.publicKey.derRepresentation,
to: to,
value: value
)
var transaction = Transaction(
id: chain.count,
metadata: metadata,
senderSignature: calculateSignature(metadata, privateKey: privateKey)
)
var hash = calculateHash(transaction)
while true {
if let validHash = hash {
if validHash.hasPrefix(String(repeating: "0", count: difficulty)) {
break
} else {
transaction.nonce += 1
hash = calculateHash(transaction)
}
} else {
return
}
}
chain.append(transaction)
}
private func calculateHash(_ transaction: Transaction) -> String? {
if let encoded = try? JSONEncoder().encode(transaction) {
return SHA256.hash(data: encoded).compactMap {
String(format: "%02x", $0)
}.joined()
}
return nil
}
private func calculateSignature(
_ metadata: Transaction.Metadata,
privateKey: P256.Signing.PrivateKey
) -> Data? {
if let encoded = try? JSONEncoder().encode(metadata) {
return try? privateKey.signature(for: encoded).derRepresentation
}
return nil
}
struct Transaction: Codable, Identifiable {
var id: Int
var metadata: Metadata
var senderSignature: Data?
var nonce = 0
struct Metadata: Codable {
var prevHash: String?
var from: Data
var to: Data
var value: Double
}
}
}
#if DEBUG
var blockchain = Blockchain(4)
let privateKey1 = P256.Signing.PrivateKey.init(compactRepresentable: false)
let publicKey1 = privateKey1.publicKey
let privateKey2 = P256.Signing.PrivateKey.init(compactRepresentable: false)
let publicKey2 = privateKey2.publicKey
blockchain.createTransaction(
to: publicKey2.derRepresentation,
privateKey: privateKey1,
value: 0
)
blockchain.createTransaction(
to: publicKey1.derRepresentation,
privateKey: privateKey2,
value: 0
)
var output = "["
for transaction in blockchain.chain {
if let encoded = try? JSONEncoder().encode(transaction) {
output += String(data: encoded, encoding: .utf8)! + ","
}
}
let _ = output.popLast()
output += "]"
print(output)
print(blockchain.isValidChain())
while true {
sleep(1000)
}
#endif