🐛 Fix node connection & sync
This commit is contained in:
@@ -45,12 +45,12 @@ Node actif: \(activeNodeName)
|
||||
""")
|
||||
|
||||
repeat {
|
||||
print("\nEntrer une commande:")
|
||||
LogManager.log("\nEntrer une commande:", level: .info)
|
||||
command = readLine()?.lowercased()
|
||||
|
||||
switch command {
|
||||
case "connect":
|
||||
print("Entrez l'adresse du pair (ex: 192.168.1.100):")
|
||||
LogManager.log("Entrez l'adresse du pair (ex: 192.168.1.100):", level: .info)
|
||||
if let host = readLine() {
|
||||
activeNode.connectToPeer(host: host)
|
||||
}
|
||||
@@ -60,69 +60,69 @@ repeat {
|
||||
|
||||
case "mine":
|
||||
if let _ = activeNode.mineBlock(minerAddress: currentMinerAddress) {
|
||||
print("Bloc miné avec succès. Récompense envoyée à \(currentMinerAddress)")
|
||||
print("Nouveau solde: \(activeNode.getBalance(currentMinerAddress))")
|
||||
LogManager.log("Bloc miné avec succès. Récompense envoyée à \(currentMinerAddress)", level: .success)
|
||||
LogManager.log("Nouveau solde: \(activeNode.getBalance(currentMinerAddress))", level: .info)
|
||||
} else {
|
||||
print("Échec du minage")
|
||||
LogManager.log("Échec du minage", level: .error)
|
||||
}
|
||||
|
||||
case "balance":
|
||||
print("Entrer l'adresse:")
|
||||
LogManager.log("Entrer l'adresse:", level: .info)
|
||||
if let address = readLine() {
|
||||
let balance = activeNode.getBalance(address)
|
||||
print("Solde de \(address): \(balance)")
|
||||
LogManager.log("Solde de \(address): \(balance)", level: .info)
|
||||
}
|
||||
|
||||
case "setminer":
|
||||
print("Nouvelle adresse du mineur:")
|
||||
LogManager.log("Nouvelle adresse du mineur:", level: .info)
|
||||
if let address = readLine() {
|
||||
currentMinerAddress = address
|
||||
print("Adresse du mineur mise à jour: \(currentMinerAddress)")
|
||||
LogManager.log("Adresse du mineur mise à jour: \(currentMinerAddress)", level: .success)
|
||||
}
|
||||
|
||||
case "pending":
|
||||
let transactions = activeNode.getPendingTransactions()
|
||||
print("Transactions en attente: \(transactions.count)")
|
||||
LogManager.log("Transactions en attente: \(transactions.count)", level: .info)
|
||||
for (index, tx) in transactions.enumerated() {
|
||||
print("""
|
||||
LogManager.log("""
|
||||
\(index + 1). De: \(tx.sender)
|
||||
À: \(tx.receiver)
|
||||
Montant: \(tx.amount)
|
||||
Type: \(tx.type)
|
||||
""")
|
||||
""", level: .info)
|
||||
}
|
||||
|
||||
case "validity":
|
||||
let isValid = activeNode.isChainValid()
|
||||
print("Chaîne valide: \(isValid)")
|
||||
LogManager.log("Chaîne valide: \(isValid)", level: .success)
|
||||
|
||||
case "exit":
|
||||
print("Au revoir!")
|
||||
LogManager.log("Au revoir!", level: .info)
|
||||
|
||||
case "createwallet":
|
||||
let wallet = Wallet()
|
||||
wallets[wallet.address] = wallet
|
||||
print("Nouveau wallet créé!")
|
||||
print("Adresse: \(wallet.address)")
|
||||
LogManager.log("Nouveau wallet créé!", level: .success)
|
||||
LogManager.log("Adresse: \(wallet.address)", level: .success)
|
||||
|
||||
case "listwallet":
|
||||
print("\nWallets disponibles:")
|
||||
LogManager.log("\nWallets disponibles:", level: .info)
|
||||
for (address, _) in wallets {
|
||||
print("- \(address) (Solde: \(activeNode.getBalance(address)))")
|
||||
LogManager.log("- \(address) (Solde: \(activeNode.getBalance(address)))", level: .info)
|
||||
}
|
||||
|
||||
case "send":
|
||||
print("Votre adresse (wallet):")
|
||||
LogManager.log("Votre adresse (wallet):", level: .info)
|
||||
guard let senderAddress = readLine(),
|
||||
let wallet = wallets[senderAddress]
|
||||
else {
|
||||
print("Wallet non trouvé")
|
||||
LogManager.log("Wallet non trouvé", level: .error)
|
||||
break
|
||||
}
|
||||
|
||||
print("Adresse du destinataire:")
|
||||
LogManager.log("Adresse du destinataire:", level: .info)
|
||||
guard let receiverAddress = readLine() else {
|
||||
print("Adresse du destinataire invalide")
|
||||
LogManager.log("Adresse du destinataire invalide", level: .error)
|
||||
break
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ repeat {
|
||||
let amount = Int(amountStr),
|
||||
amount > 0
|
||||
else {
|
||||
print("Montant invalide")
|
||||
LogManager.log("Montant invalide", level: .error)
|
||||
break
|
||||
}
|
||||
|
||||
@@ -146,12 +146,12 @@ repeat {
|
||||
if let signature = wallet.signTransaction(transaction) {
|
||||
transaction.signature = signature
|
||||
if activeNode.submitTransaction(transaction) {
|
||||
print("Transaction signée et propagée au réseau!")
|
||||
LogManager.log("Transaction signée et propagée au réseau!", level: .success)
|
||||
} else {
|
||||
print("Erreur lors de l'envoi de la transaction")
|
||||
LogManager.log("Erreur lors de l'envoi de la transaction", level: .error)
|
||||
}
|
||||
} else {
|
||||
print("Erreur lors de la signature de la transaction")
|
||||
LogManager.log("Erreur lors de la signature de la transaction", level: .error)
|
||||
}
|
||||
|
||||
case "mempool":
|
||||
@@ -165,10 +165,10 @@ repeat {
|
||||
activeNode = node1
|
||||
activeNodeName = "Node 1"
|
||||
}
|
||||
print("Node actif: \(activeNodeName)")
|
||||
LogManager.log("Node actif: \(activeNodeName)", level: .info)
|
||||
|
||||
default:
|
||||
print("Commande inconnue")
|
||||
LogManager.log("Commande inconnue", level: .error)
|
||||
}
|
||||
|
||||
} while command != "exit"
|
||||
|
||||
38
SwiftChainCore/Models/LogManager.swift
Normal file
38
SwiftChainCore/Models/LogManager.swift
Normal file
@@ -0,0 +1,38 @@
|
||||
//
|
||||
// LogManager.swift
|
||||
// SwiftChain
|
||||
//
|
||||
// Created by Victor on 05/05/2025.
|
||||
//
|
||||
|
||||
import os.log
|
||||
|
||||
public struct LogManager {
|
||||
public enum LogLevel: String {
|
||||
case info = "INFO"
|
||||
case success = "SUCCÈS"
|
||||
case warning = "ATTENTION"
|
||||
case error = "ERREUR"
|
||||
case network = "RÉSEAU"
|
||||
case blockchain = "BLOCKCHAIN"
|
||||
|
||||
var logType: OSLogType {
|
||||
switch self {
|
||||
case .info, .success: return .info
|
||||
case .warning: return .debug
|
||||
case .error: return .error
|
||||
case .network, .blockchain: return .default
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static let log = OSLog(subsystem: "com.votreapp.swiftchain", category: "blockchain")
|
||||
|
||||
public static func log(_ message: String, level: LogLevel) {
|
||||
os_log("%{public}@: %{public}@", log: log, type: level.logType, level.rawValue, message)
|
||||
|
||||
// Également afficher dans la console pour le CLI
|
||||
let timestamp = DateFormatter.localizedString(from: Date(), dateStyle: .none, timeStyle: .medium)
|
||||
print("[\(timestamp)] [\(level.rawValue)] \(message)")
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,9 @@ import Foundation
|
||||
import Network
|
||||
|
||||
public class Node {
|
||||
private let nodeId = UUID().uuidString // Identifiant unique pour chaque nœud
|
||||
private var processedMessages = Set<String>() // Pour traquer les messages déjà traités
|
||||
|
||||
// Network properties
|
||||
private var peers: [NWConnection] = []
|
||||
private var port: NWEndpoint.Port
|
||||
@@ -38,6 +41,15 @@ public class Node {
|
||||
struct NetworkMessage: Codable {
|
||||
let type: MessageType
|
||||
let data: Data
|
||||
let senderId: String // Identifiant du nœud émetteur
|
||||
let messageId: String // Identifiant unique du message
|
||||
|
||||
init(type: MessageType, data: Data, senderId: String) {
|
||||
self.type = type
|
||||
self.data = data
|
||||
self.senderId = senderId
|
||||
self.messageId = UUID().uuidString
|
||||
}
|
||||
}
|
||||
|
||||
// Configuration du listener
|
||||
@@ -178,7 +190,7 @@ public class Node {
|
||||
func broadcastTransaction(_ transaction: Transaction) {
|
||||
do {
|
||||
let transactionData = try JSONEncoder().encode(transaction)
|
||||
let message = NetworkMessage(type: .transaction, data: transactionData)
|
||||
let message = NetworkMessage(type: .transaction, data: transactionData, senderId: nodeId)
|
||||
let messageData = try JSONEncoder().encode(message)
|
||||
|
||||
print("Broadcasting transaction to \(peers.count) peers")
|
||||
@@ -220,6 +232,15 @@ public class Node {
|
||||
let message = try JSONDecoder().decode(NetworkMessage.self, from: data)
|
||||
print("Message decoded successfully, type: \(message.type)")
|
||||
|
||||
// Vérifier si le message a déjà été traité
|
||||
if processedMessages.contains(message.messageId) {
|
||||
print("Message déjà traité, ignoré")
|
||||
return
|
||||
}
|
||||
|
||||
// Ajouter le message à la liste des messages traités
|
||||
processedMessages.insert(message.messageId)
|
||||
|
||||
switch message.type {
|
||||
case .transaction:
|
||||
let transaction = try JSONDecoder().decode(Transaction.self, from: message.data)
|
||||
@@ -261,7 +282,7 @@ public class Node {
|
||||
|
||||
private func requestBlockchain(from peer: NWConnection) {
|
||||
do {
|
||||
let message = NetworkMessage(type: .blockchainRequest, data: Data())
|
||||
let message = NetworkMessage(type: .blockchainRequest, data: Data(), senderId: nodeId)
|
||||
let messageData = try JSONEncoder().encode(message)
|
||||
|
||||
peer.send(content: messageData, completion: .contentProcessed { error in
|
||||
@@ -279,7 +300,7 @@ public class Node {
|
||||
private func sendBlockchain(to peer: NWConnection) {
|
||||
do {
|
||||
let chainData = try JSONEncoder().encode(blockchain.chain)
|
||||
let message = NetworkMessage(type: .blockchainResponse, data: chainData)
|
||||
let message = NetworkMessage(type: .blockchainResponse, data: chainData, senderId: nodeId)
|
||||
let messageData = try JSONEncoder().encode(message)
|
||||
|
||||
peer.send(content: messageData, completion: .contentProcessed { error in
|
||||
@@ -331,6 +352,11 @@ public class Node {
|
||||
private func handleReceivedBlock(_ block: Block) {
|
||||
print("Received new block: \(block.hash)")
|
||||
|
||||
if blockchain.chain.contains(where: { $0.hash == block.hash }) {
|
||||
print("Bloc déjà dans la chaîne")
|
||||
return
|
||||
}
|
||||
|
||||
// Vérifier que le bloc suit bien notre dernier bloc
|
||||
guard let lastBlock = blockchain.chain.last else {
|
||||
print("No existing chain")
|
||||
@@ -338,7 +364,13 @@ public class Node {
|
||||
}
|
||||
|
||||
if block.previousHash != lastBlock.hash {
|
||||
print("Block does not connect to our chain")
|
||||
print("Le bloc ne se connecte pas à notre chaîne")
|
||||
|
||||
// Demander la chaîne complète aux pairs pour se synchroniser
|
||||
for peer in peers {
|
||||
requestBlockchain(from: peer)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -367,7 +399,7 @@ public class Node {
|
||||
private func broadcastBlock(_ block: Block) {
|
||||
do {
|
||||
let blockData = try JSONEncoder().encode(block)
|
||||
let message = NetworkMessage(type: .newBlock, data: blockData)
|
||||
let message = NetworkMessage(type: .newBlock, data: blockData, senderId: nodeId)
|
||||
let messageData = try JSONEncoder().encode(message)
|
||||
|
||||
print("Broadcasting block to peers")
|
||||
|
||||
Reference in New Issue
Block a user