🐛 Fix node connection & sync
This commit is contained in:
@@ -45,12 +45,12 @@ Node actif: \(activeNodeName)
|
|||||||
""")
|
""")
|
||||||
|
|
||||||
repeat {
|
repeat {
|
||||||
print("\nEntrer une commande:")
|
LogManager.log("\nEntrer une commande:", level: .info)
|
||||||
command = readLine()?.lowercased()
|
command = readLine()?.lowercased()
|
||||||
|
|
||||||
switch command {
|
switch command {
|
||||||
case "connect":
|
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() {
|
if let host = readLine() {
|
||||||
activeNode.connectToPeer(host: host)
|
activeNode.connectToPeer(host: host)
|
||||||
}
|
}
|
||||||
@@ -60,69 +60,69 @@ repeat {
|
|||||||
|
|
||||||
case "mine":
|
case "mine":
|
||||||
if let _ = activeNode.mineBlock(minerAddress: currentMinerAddress) {
|
if let _ = activeNode.mineBlock(minerAddress: currentMinerAddress) {
|
||||||
print("Bloc miné avec succès. Récompense envoyée à \(currentMinerAddress)")
|
LogManager.log("Bloc miné avec succès. Récompense envoyée à \(currentMinerAddress)", level: .success)
|
||||||
print("Nouveau solde: \(activeNode.getBalance(currentMinerAddress))")
|
LogManager.log("Nouveau solde: \(activeNode.getBalance(currentMinerAddress))", level: .info)
|
||||||
} else {
|
} else {
|
||||||
print("Échec du minage")
|
LogManager.log("Échec du minage", level: .error)
|
||||||
}
|
}
|
||||||
|
|
||||||
case "balance":
|
case "balance":
|
||||||
print("Entrer l'adresse:")
|
LogManager.log("Entrer l'adresse:", level: .info)
|
||||||
if let address = readLine() {
|
if let address = readLine() {
|
||||||
let balance = activeNode.getBalance(address)
|
let balance = activeNode.getBalance(address)
|
||||||
print("Solde de \(address): \(balance)")
|
LogManager.log("Solde de \(address): \(balance)", level: .info)
|
||||||
}
|
}
|
||||||
|
|
||||||
case "setminer":
|
case "setminer":
|
||||||
print("Nouvelle adresse du mineur:")
|
LogManager.log("Nouvelle adresse du mineur:", level: .info)
|
||||||
if let address = readLine() {
|
if let address = readLine() {
|
||||||
currentMinerAddress = address
|
currentMinerAddress = address
|
||||||
print("Adresse du mineur mise à jour: \(currentMinerAddress)")
|
LogManager.log("Adresse du mineur mise à jour: \(currentMinerAddress)", level: .success)
|
||||||
}
|
}
|
||||||
|
|
||||||
case "pending":
|
case "pending":
|
||||||
let transactions = activeNode.getPendingTransactions()
|
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() {
|
for (index, tx) in transactions.enumerated() {
|
||||||
print("""
|
LogManager.log("""
|
||||||
\(index + 1). De: \(tx.sender)
|
\(index + 1). De: \(tx.sender)
|
||||||
À: \(tx.receiver)
|
À: \(tx.receiver)
|
||||||
Montant: \(tx.amount)
|
Montant: \(tx.amount)
|
||||||
Type: \(tx.type)
|
Type: \(tx.type)
|
||||||
""")
|
""", level: .info)
|
||||||
}
|
}
|
||||||
|
|
||||||
case "validity":
|
case "validity":
|
||||||
let isValid = activeNode.isChainValid()
|
let isValid = activeNode.isChainValid()
|
||||||
print("Chaîne valide: \(isValid)")
|
LogManager.log("Chaîne valide: \(isValid)", level: .success)
|
||||||
|
|
||||||
case "exit":
|
case "exit":
|
||||||
print("Au revoir!")
|
LogManager.log("Au revoir!", level: .info)
|
||||||
|
|
||||||
case "createwallet":
|
case "createwallet":
|
||||||
let wallet = Wallet()
|
let wallet = Wallet()
|
||||||
wallets[wallet.address] = wallet
|
wallets[wallet.address] = wallet
|
||||||
print("Nouveau wallet créé!")
|
LogManager.log("Nouveau wallet créé!", level: .success)
|
||||||
print("Adresse: \(wallet.address)")
|
LogManager.log("Adresse: \(wallet.address)", level: .success)
|
||||||
|
|
||||||
case "listwallet":
|
case "listwallet":
|
||||||
print("\nWallets disponibles:")
|
LogManager.log("\nWallets disponibles:", level: .info)
|
||||||
for (address, _) in wallets {
|
for (address, _) in wallets {
|
||||||
print("- \(address) (Solde: \(activeNode.getBalance(address)))")
|
LogManager.log("- \(address) (Solde: \(activeNode.getBalance(address)))", level: .info)
|
||||||
}
|
}
|
||||||
|
|
||||||
case "send":
|
case "send":
|
||||||
print("Votre adresse (wallet):")
|
LogManager.log("Votre adresse (wallet):", level: .info)
|
||||||
guard let senderAddress = readLine(),
|
guard let senderAddress = readLine(),
|
||||||
let wallet = wallets[senderAddress]
|
let wallet = wallets[senderAddress]
|
||||||
else {
|
else {
|
||||||
print("Wallet non trouvé")
|
LogManager.log("Wallet non trouvé", level: .error)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
print("Adresse du destinataire:")
|
LogManager.log("Adresse du destinataire:", level: .info)
|
||||||
guard let receiverAddress = readLine() else {
|
guard let receiverAddress = readLine() else {
|
||||||
print("Adresse du destinataire invalide")
|
LogManager.log("Adresse du destinataire invalide", level: .error)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,7 +131,7 @@ repeat {
|
|||||||
let amount = Int(amountStr),
|
let amount = Int(amountStr),
|
||||||
amount > 0
|
amount > 0
|
||||||
else {
|
else {
|
||||||
print("Montant invalide")
|
LogManager.log("Montant invalide", level: .error)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,12 +146,12 @@ repeat {
|
|||||||
if let signature = wallet.signTransaction(transaction) {
|
if let signature = wallet.signTransaction(transaction) {
|
||||||
transaction.signature = signature
|
transaction.signature = signature
|
||||||
if activeNode.submitTransaction(transaction) {
|
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 {
|
} else {
|
||||||
print("Erreur lors de l'envoi de la transaction")
|
LogManager.log("Erreur lors de l'envoi de la transaction", level: .error)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
print("Erreur lors de la signature de la transaction")
|
LogManager.log("Erreur lors de la signature de la transaction", level: .error)
|
||||||
}
|
}
|
||||||
|
|
||||||
case "mempool":
|
case "mempool":
|
||||||
@@ -165,10 +165,10 @@ repeat {
|
|||||||
activeNode = node1
|
activeNode = node1
|
||||||
activeNodeName = "Node 1"
|
activeNodeName = "Node 1"
|
||||||
}
|
}
|
||||||
print("Node actif: \(activeNodeName)")
|
LogManager.log("Node actif: \(activeNodeName)", level: .info)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
print("Commande inconnue")
|
LogManager.log("Commande inconnue", level: .error)
|
||||||
}
|
}
|
||||||
|
|
||||||
} while command != "exit"
|
} 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
|
import Network
|
||||||
|
|
||||||
public class Node {
|
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
|
// Network properties
|
||||||
private var peers: [NWConnection] = []
|
private var peers: [NWConnection] = []
|
||||||
private var port: NWEndpoint.Port
|
private var port: NWEndpoint.Port
|
||||||
@@ -38,6 +41,15 @@ public class Node {
|
|||||||
struct NetworkMessage: Codable {
|
struct NetworkMessage: Codable {
|
||||||
let type: MessageType
|
let type: MessageType
|
||||||
let data: Data
|
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
|
// Configuration du listener
|
||||||
@@ -178,7 +190,7 @@ public class Node {
|
|||||||
func broadcastTransaction(_ transaction: Transaction) {
|
func broadcastTransaction(_ transaction: Transaction) {
|
||||||
do {
|
do {
|
||||||
let transactionData = try JSONEncoder().encode(transaction)
|
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)
|
let messageData = try JSONEncoder().encode(message)
|
||||||
|
|
||||||
print("Broadcasting transaction to \(peers.count) peers")
|
print("Broadcasting transaction to \(peers.count) peers")
|
||||||
@@ -220,6 +232,15 @@ public class Node {
|
|||||||
let message = try JSONDecoder().decode(NetworkMessage.self, from: data)
|
let message = try JSONDecoder().decode(NetworkMessage.self, from: data)
|
||||||
print("Message decoded successfully, type: \(message.type)")
|
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 {
|
switch message.type {
|
||||||
case .transaction:
|
case .transaction:
|
||||||
let transaction = try JSONDecoder().decode(Transaction.self, from: message.data)
|
let transaction = try JSONDecoder().decode(Transaction.self, from: message.data)
|
||||||
@@ -261,7 +282,7 @@ public class Node {
|
|||||||
|
|
||||||
private func requestBlockchain(from peer: NWConnection) {
|
private func requestBlockchain(from peer: NWConnection) {
|
||||||
do {
|
do {
|
||||||
let message = NetworkMessage(type: .blockchainRequest, data: Data())
|
let message = NetworkMessage(type: .blockchainRequest, data: Data(), senderId: nodeId)
|
||||||
let messageData = try JSONEncoder().encode(message)
|
let messageData = try JSONEncoder().encode(message)
|
||||||
|
|
||||||
peer.send(content: messageData, completion: .contentProcessed { error in
|
peer.send(content: messageData, completion: .contentProcessed { error in
|
||||||
@@ -279,7 +300,7 @@ public class Node {
|
|||||||
private func sendBlockchain(to peer: NWConnection) {
|
private func sendBlockchain(to peer: NWConnection) {
|
||||||
do {
|
do {
|
||||||
let chainData = try JSONEncoder().encode(blockchain.chain)
|
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)
|
let messageData = try JSONEncoder().encode(message)
|
||||||
|
|
||||||
peer.send(content: messageData, completion: .contentProcessed { error in
|
peer.send(content: messageData, completion: .contentProcessed { error in
|
||||||
@@ -331,6 +352,11 @@ public class Node {
|
|||||||
private func handleReceivedBlock(_ block: Block) {
|
private func handleReceivedBlock(_ block: Block) {
|
||||||
print("Received new block: \(block.hash)")
|
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
|
// Vérifier que le bloc suit bien notre dernier bloc
|
||||||
guard let lastBlock = blockchain.chain.last else {
|
guard let lastBlock = blockchain.chain.last else {
|
||||||
print("No existing chain")
|
print("No existing chain")
|
||||||
@@ -338,7 +364,13 @@ public class Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if block.previousHash != lastBlock.hash {
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -367,7 +399,7 @@ public class Node {
|
|||||||
private func broadcastBlock(_ block: Block) {
|
private func broadcastBlock(_ block: Block) {
|
||||||
do {
|
do {
|
||||||
let blockData = try JSONEncoder().encode(block)
|
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)
|
let messageData = try JSONEncoder().encode(message)
|
||||||
|
|
||||||
print("Broadcasting block to peers")
|
print("Broadcasting block to peers")
|
||||||
|
|||||||
Reference in New Issue
Block a user