Files
SwiftChain/SwiftChain/Models/Blockchain.swift
Victor Bodinaud 1943a478fa Add p2p
2024-11-27 20:37:38 +01:00

120 lines
3.5 KiB
Swift

//
// Blockchain.swift
// Blockchain
//
// Created by Victor BODINAUD on 27/02/2020.
// Copyright © 2020 Victor BODINAUD. All rights reserved.
//
import Foundation
class Blockchain {
var chain = [Block]()
let memPool: MemPool
let accountManager: AccountManager
let minDifficulty = 2
let maxDifficulty = 6
let targetBlockTime = 10.0 // en secondes
init() {
self.accountManager = AccountManager()
self.memPool = MemPool(accountManager: accountManager)
}
/**
Initialize the first block of the blockchain.
- Parameters:
- data: The datas of the block
*/
func createGenesisBlock() {
let genesisBlock = Block()
genesisBlock.previousHash = "0000"
genesisBlock.index = 0
genesisBlock.timestamp = Int(Date().timeIntervalSince1970)
let _ = genesisBlock.mineBlock()
chain.append(genesisBlock)
print("Genesis block created -- hash: \(genesisBlock.hash)")
}
/**
Initialize a new block of the blockchain.
- Parameters:
- data: The datas of the block
*/
func createBlock(minerAddress: String) -> Block? {
guard let lastBlock = chain.last else { return nil }
// Récupérer les transactions en attente
var transactions = memPool.getTransactionsForBlock()
// Ajouter la récompense de minage
let miningReward = Transaction(sender: "SYSTEM", receiver: minerAddress, amount: 50, type: "MINING_REWARD")
transactions.append(miningReward)
let newBlock = Block(
transactions: transactions,
previousHash: lastBlock.hash,
index: chain.count,
difficulty: calculateNewDifficulty()
)
newBlock.miner = minerAddress
newBlock.timestamp = Int(Date().timeIntervalSince1970)
let miningTime = newBlock.mineBlock()
// Valider et traiter les transactions
if accountManager.processBlock(newBlock) {
chain.append(newBlock)
print("""
Block \(newBlock.index) created:
Hash: \(newBlock.hash)
Previous hash: \(newBlock.previousHash)
Transactions: \(newBlock.transactions.count)
Mining time: \(String(format: "%.2f", miningTime)) seconds
""")
return newBlock
}
return nil
}
private func calculateNewDifficulty() -> Int {
guard chain.count >= 2 else { return minDifficulty }
let lastBlock = chain.last!
let previousBlock = chain[chain.count - 2]
let timeSpent = Double(lastBlock.timestamp - previousBlock.timestamp)
if timeSpent < targetBlockTime / 2 {
return min(lastBlock.difficulty + 1, maxDifficulty)
} else if timeSpent > targetBlockTime * 2 {
return max(lastBlock.difficulty - 1, minDifficulty)
}
return lastBlock.difficulty
}
func submitTransaction(_ transaction: Transaction) -> Bool {
return memPool.addTransaction(transaction)
}
func getBalance(address: String) -> Int {
return accountManager.getBalance(address)
}
func chainValidity() -> Bool {
for i in 1..<chain.count {
let currentBlock = chain[i]
let previousBlock = chain[i-1]
if !currentBlock.isValid() || currentBlock.previousHash != previousBlock.hash {
print("Chain invalid at block \(i)")
return false
}
}
return true
}
}