🐛 Change sync to be more consistent

This commit is contained in:
Victor Bodinaud
2024-11-30 12:18:19 +01:00
parent 22d8b22ea1
commit 358bdda5a6
3 changed files with 90 additions and 27 deletions

View File

@@ -20,9 +20,9 @@ class Blockchain {
let block = Block() let block = Block()
block.previousHash = "0000genesis0000" block.previousHash = "0000genesis0000"
block.index = 0 block.index = 0
block.timestamp = 1701388800 // 1er Décembre 2023 00:00:00 GMT block.timestamp = 1701388800
block.difficulty = 4 block.difficulty = 4
block.nonce = 12345 // Nonce précalculé qui donne un hash valide block.nonce = 12345
block.hash = "000088c1731bed4996680d2c50ea3d9b573c1507d2d61866c0deff33a7f8cf5e" block.hash = "000088c1731bed4996680d2c50ea3d9b573c1507d2d61866c0deff33a7f8cf5e"
return block return block
}() }()
@@ -86,7 +86,7 @@ class Blockchain {
return nil return nil
} }
private func calculateNewDifficulty() -> Int { func calculateNewDifficulty() -> Int {
guard chain.count >= 2 else { return minDifficulty } guard chain.count >= 2 else { return minDifficulty }
let lastBlock = chain.last! let lastBlock = chain.last!
@@ -123,18 +123,18 @@ class Blockchain {
return true 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 // 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 { firstBlock.hash == Blockchain.genesisBlock.hash else {
print("Genesis block mismatch") print("Genesis block mismatch")
return false return false
} }
// Vérifier les blocs suivants // Vérifier les blocs suivants
for i in 1..<newChain.count { for i in 1..<chain.count {
let block = newChain[i] let block = chain[i]
let previousBlock = newChain[i-1] let previousBlock = chain[i-1]
if block.previousHash != previousBlock.hash { if block.previousHash != previousBlock.hash {
print("Invalid chain at block \(i): incorrect previous hash") print("Invalid chain at block \(i): incorrect previous hash")

View File

@@ -10,15 +10,19 @@ import Network
class Node { class Node {
private var peers: [NWConnection] = [] private var peers: [NWConnection] = []
private let port: NWEndpoint.Port = 8333 // Port standard private let port: NWEndpoint.Port = 8333
private var listener: NWListener? private var listener: NWListener?
private let blockchain: Blockchain
// Le node possède et gère la blockchain
private let blockchain = Blockchain()
private let memPool: MemPool
private let accountManager = AccountManager()
// Queue pour gérer les connexions de manière asynchrone // Queue pour gérer les connexions de manière asynchrone
private let queue = DispatchQueue(label: "com.blockchain.node") private let queue = DispatchQueue(label: "com.blockchain.node")
init(blockchain: Blockchain) { init() {
self.blockchain = blockchain self.memPool = MemPool(accountManager: accountManager)
setupListener() setupListener()
} }
@@ -61,6 +65,71 @@ class Node {
} }
} }
func mineBlock(minerAddress: String) -> 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 // Connexion à un pair
func connectToPeer(host: String) { func connectToPeer(host: String) {
let endpoint = NWEndpoint.hostPort(host: NWEndpoint.Host(host), port: port) let endpoint = NWEndpoint.hostPort(host: NWEndpoint.Host(host), port: port)

View File

@@ -8,10 +8,9 @@
import Foundation import Foundation
let blockchain = Blockchain() let node = Node()
let node = Node(blockchain: blockchain)
var command: String? var command: String?
var currentMinerAddress = "MINER1" // Adresse par défaut du mineur var currentMinerAddress = "MINER1"
var wallets: [String: Wallet] = [:] var wallets: [String: Wallet] = [:]
print(""" print("""
@@ -27,8 +26,6 @@ Blockchain CLI - Commandes disponibles:
- exit : Quitter - exit : Quitter
""") """)
blockchain.createGenesisBlock()
repeat { repeat {
print("\nEntrer une commande:") print("\nEntrer une commande:")
command = readLine()?.lowercased() command = readLine()?.lowercased()
@@ -44,9 +41,9 @@ repeat {
node.listPeers() node.listPeers()
case "mine": 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("Bloc miné avec succès. Récompense envoyée à \(currentMinerAddress)")
print("Nouveau solde: \(blockchain.getBalance(address: currentMinerAddress))") print("Nouveau solde: \(node.getBalance(currentMinerAddress))")
} else { } else {
print("Échec du minage") print("Échec du minage")
} }
@@ -54,7 +51,7 @@ repeat {
case "balance": case "balance":
print("Entrer l'adresse:") print("Entrer l'adresse:")
if let address = readLine() { if let address = readLine() {
let balance = blockchain.getBalance(address: address) let balance = node.getBalance(address)
print("Solde de \(address): \(balance)") print("Solde de \(address): \(balance)")
} }
@@ -66,7 +63,7 @@ repeat {
} }
case "pending": case "pending":
let transactions = blockchain.memPool.getAllPendingTransactions() let transactions = node.getPendingTransactions()
print("Transactions en attente: \(transactions.count)") print("Transactions en attente: \(transactions.count)")
for (index, tx) in transactions.enumerated() { for (index, tx) in transactions.enumerated() {
print(""" print("""
@@ -78,7 +75,7 @@ repeat {
} }
case "validity": case "validity":
let isValid = blockchain.chainValidity() let isValid = node.isChainValid()
print("Chaîne valide: \(isValid)") print("Chaîne valide: \(isValid)")
case "exit": case "exit":
@@ -91,12 +88,10 @@ repeat {
print("Nouveau wallet créé!") print("Nouveau wallet créé!")
print("Adresse: \(wallet.address)") print("Adresse: \(wallet.address)")
// Modifions la commande send
case "send": case "send":
print("Votre adresse (wallet):") print("Votre adresse (wallet):")
guard let senderAddress = readLine(), guard let senderAddress = readLine(),
let wallet = wallets[senderAddress] let wallet = wallets[senderAddress] else {
else {
print("Wallet non trouvé") print("Wallet non trouvé")
break break
} }
@@ -119,8 +114,7 @@ repeat {
transaction.senderPublicKey = wallet.getPublicKeyData() transaction.senderPublicKey = wallet.getPublicKeyData()
transaction.signature = wallet.signTransaction(transaction) transaction.signature = wallet.signTransaction(transaction)
if blockchain.submitTransaction(transaction) { if node.submitTransaction(transaction) {
node.broadcastTransaction(transaction)
print("Transaction propagée au réseau!") print("Transaction propagée au réseau!")
} else { } else {
print("Erreur lors de l'envoi de la transaction") print("Erreur lors de l'envoi de la transaction")