🐛 Fix node connection & sync

This commit is contained in:
Victor Bodinaud
2025-05-05 16:58:52 +02:00
parent 7a71c6bbfe
commit cba2a778c3
3 changed files with 103 additions and 33 deletions

View File

@@ -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"

View 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)")
}
}

View File

@@ -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")