diff --git a/SwiftChain/Models/Blockchain.swift b/SwiftChain/Models/Blockchain.swift index a00ee33..d962e5f 100644 --- a/SwiftChain/Models/Blockchain.swift +++ b/SwiftChain/Models/Blockchain.swift @@ -20,9 +20,9 @@ class Blockchain { let block = Block() block.previousHash = "0000genesis0000" block.index = 0 - block.timestamp = 1701388800 // 1er Décembre 2023 00:00:00 GMT + block.timestamp = 1701388800 block.difficulty = 4 - block.nonce = 12345 // Nonce précalculé qui donne un hash valide + block.nonce = 12345 block.hash = "000088c1731bed4996680d2c50ea3d9b573c1507d2d61866c0deff33a7f8cf5e" return block }() @@ -86,7 +86,7 @@ class Blockchain { return nil } - private func calculateNewDifficulty() -> Int { + func calculateNewDifficulty() -> Int { guard chain.count >= 2 else { return minDifficulty } let lastBlock = chain.last! @@ -123,18 +123,18 @@ class Blockchain { return true } - func validateChain(_ newChain: [Block]) -> Bool { + func validateChain(_ chain: [Block]) -> Bool { // Vérifier que la chaîne commence par notre bloc genesis codé en dur - guard let firstBlock = newChain.first, + guard let firstBlock = chain.first, firstBlock.hash == Blockchain.genesisBlock.hash else { print("Genesis block mismatch") return false } // Vérifier les blocs suivants - for i in 1.. Block? { + guard let lastBlock = blockchain.chain.last else { return nil } + + // Récupérer les transactions du mempool + var transactions = memPool.getTransactionsForBlock() + + // Créer la récompense de minage + let miningReward = Transaction( + sender: "SYSTEM", + receiver: minerAddress, + amount: 50, + type: "MINING_REWARD" + ) + transactions.append(miningReward) + + // Créer et miner le bloc + let newBlock = Block( + transactions: transactions, + previousHash: lastBlock.hash, + index: blockchain.chain.count, + difficulty: blockchain.calculateNewDifficulty() + ) + + newBlock.miner = minerAddress + newBlock.timestamp = Int(Date().timeIntervalSince1970) + let miningTime = newBlock.mineBlock() + + // Valider et traiter les transactions + if accountManager.processBlock(newBlock) { + blockchain.chain.append(newBlock) + broadcastBlock(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 + } + + func submitTransaction(_ transaction: Transaction) -> Bool { + if memPool.addTransaction(transaction) { + broadcastTransaction(transaction) + return true + } + return false + } + + func getBalance(_ address: String) -> Int { + return accountManager.getBalance(address) + } + + func getPendingTransactions() -> [Transaction] { + return memPool.getAllPendingTransactions() + } + + func isChainValid() -> Bool { + return blockchain.validateChain(blockchain.chain) + } + // Connexion à un pair func connectToPeer(host: String) { let endpoint = NWEndpoint.hostPort(host: NWEndpoint.Host(host), port: port) diff --git a/SwiftChain/main.swift b/SwiftChain/main.swift index 09a8d1c..9ee8477 100644 --- a/SwiftChain/main.swift +++ b/SwiftChain/main.swift @@ -8,10 +8,9 @@ import Foundation -let blockchain = Blockchain() -let node = Node(blockchain: blockchain) +let node = Node() var command: String? -var currentMinerAddress = "MINER1" // Adresse par défaut du mineur +var currentMinerAddress = "MINER1" var wallets: [String: Wallet] = [:] print(""" @@ -27,8 +26,6 @@ Blockchain CLI - Commandes disponibles: - exit : Quitter """) -blockchain.createGenesisBlock() - repeat { print("\nEntrer une commande:") command = readLine()?.lowercased() @@ -44,9 +41,9 @@ repeat { node.listPeers() case "mine": - if let block = blockchain.createBlock(minerAddress: currentMinerAddress) { + if let block = node.mineBlock(minerAddress: currentMinerAddress) { print("Bloc miné avec succès. Récompense envoyée à \(currentMinerAddress)") - print("Nouveau solde: \(blockchain.getBalance(address: currentMinerAddress))") + print("Nouveau solde: \(node.getBalance(currentMinerAddress))") } else { print("Échec du minage") } @@ -54,7 +51,7 @@ repeat { case "balance": print("Entrer l'adresse:") if let address = readLine() { - let balance = blockchain.getBalance(address: address) + let balance = node.getBalance(address) print("Solde de \(address): \(balance)") } @@ -66,7 +63,7 @@ repeat { } case "pending": - let transactions = blockchain.memPool.getAllPendingTransactions() + let transactions = node.getPendingTransactions() print("Transactions en attente: \(transactions.count)") for (index, tx) in transactions.enumerated() { print(""" @@ -78,7 +75,7 @@ repeat { } case "validity": - let isValid = blockchain.chainValidity() + let isValid = node.isChainValid() print("Chaîne valide: \(isValid)") case "exit": @@ -91,12 +88,10 @@ repeat { print("Nouveau wallet créé!") print("Adresse: \(wallet.address)") - // Modifions la commande send case "send": print("Votre adresse (wallet):") guard let senderAddress = readLine(), - let wallet = wallets[senderAddress] - else { + let wallet = wallets[senderAddress] else { print("Wallet non trouvé") break } @@ -119,8 +114,7 @@ repeat { transaction.senderPublicKey = wallet.getPublicKeyData() transaction.signature = wallet.signTransaction(transaction) - if blockchain.submitTransaction(transaction) { - node.broadcastTransaction(transaction) + if node.submitTransaction(transaction) { print("Transaction propagée au réseau!") } else { print("Erreur lors de l'envoi de la transaction")