✨Add mempool & transactions
This commit is contained in:
@@ -10,79 +10,110 @@ import Foundation
|
||||
|
||||
class Blockchain {
|
||||
var chain = [Block]()
|
||||
|
||||
let memPool: MemPool
|
||||
let accountManager: AccountManager
|
||||
let minDifficulty = 2
|
||||
let maxDifficulty = 6
|
||||
let targetBlockTime = 10.0 // en secondes
|
||||
|
||||
init() {
|
||||
self.accountManager = AccountManager()
|
||||
self.memPool = MemPool(accountManager: accountManager)
|
||||
}
|
||||
|
||||
/**
|
||||
Initialize the first block of the blockchain.
|
||||
|
||||
- Parameters:
|
||||
- data: The datas of the block
|
||||
*/
|
||||
func createGenesisBlock(data: String) {
|
||||
func createGenesisBlock() {
|
||||
let genesisBlock = Block()
|
||||
genesisBlock.data = data
|
||||
genesisBlock.previousHash = "0000"
|
||||
genesisBlock.index = 0
|
||||
genesisBlock.nonce = 0
|
||||
genesisBlock.timestamp = genesisBlock.generateTimestamp()
|
||||
genesisBlock.hash = genesisBlock.generateHash()
|
||||
genesisBlock.timestamp = Int(Date().timeIntervalSince1970)
|
||||
genesisBlock.mineBlock()
|
||||
chain.append(genesisBlock)
|
||||
print("Genesis block created -- hash: \(genesisBlock.hash)")
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Initialize a new block of the blockchain.
|
||||
|
||||
- Parameters:
|
||||
- data: The datas of the block
|
||||
*/
|
||||
func createBlock(data: String) {
|
||||
let newBlock = Block()
|
||||
newBlock.data = data
|
||||
newBlock.previousHash = chain.last!.hash
|
||||
newBlock.index = chain.count
|
||||
newBlock.nonce = 0
|
||||
newBlock.timestamp = newBlock.generateTimestamp()
|
||||
newBlock.hash = newBlock.generateHash()
|
||||
chain.append(newBlock)
|
||||
|
||||
print("-- Block \(newBlock.index) created --\n hash: \(newBlock.hash)\n previous hash: \(newBlock.previousHash)\n data: \(newBlock.data)")
|
||||
func createBlock(minerAddress: String) -> Block? {
|
||||
guard let lastBlock = chain.last else { return nil }
|
||||
|
||||
// Récupérer les transactions en attente
|
||||
var transactions = memPool.getTransactionsForBlock()
|
||||
|
||||
// Ajouter la récompense de minage
|
||||
let miningReward = Transaction(sender: "SYSTEM", receiver: minerAddress, amount: 50, type: "MINING_REWARD")
|
||||
transactions.append(miningReward)
|
||||
|
||||
let newBlock = Block(
|
||||
transactions: transactions,
|
||||
previousHash: lastBlock.hash,
|
||||
index: chain.count,
|
||||
difficulty: calculateNewDifficulty()
|
||||
)
|
||||
|
||||
newBlock.miner = minerAddress
|
||||
newBlock.timestamp = Int(Date().timeIntervalSince1970)
|
||||
let miningTime = newBlock.mineBlock()
|
||||
|
||||
// Valider et traiter les transactions
|
||||
if accountManager.processBlock(newBlock) {
|
||||
chain.append(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
|
||||
}
|
||||
|
||||
/**
|
||||
Insert a corrupted block in the blockhain.
|
||||
(for testing purpose)
|
||||
*/
|
||||
func insertCorruptedBlock() {
|
||||
let newCorruptedBlock = Block()
|
||||
newCorruptedBlock.data = "Corrupted block"
|
||||
newCorruptedBlock.previousHash = "1234567890"
|
||||
newCorruptedBlock.index = chain.count
|
||||
newCorruptedBlock.nonce = 0
|
||||
newCorruptedBlock.timestamp = newCorruptedBlock.generateTimestamp()
|
||||
newCorruptedBlock.hash = newCorruptedBlock.generateHash()
|
||||
chain.append(newCorruptedBlock)
|
||||
|
||||
print("-- Corrupted block \(newCorruptedBlock.index) created --\n hash: \(newCorruptedBlock.hash)\n previous hash: \(newCorruptedBlock.previousHash)\n data: \(newCorruptedBlock.data)")
|
||||
|
||||
private func calculateNewDifficulty() -> Int {
|
||||
guard chain.count >= 2 else { return minDifficulty }
|
||||
|
||||
let lastBlock = chain.last!
|
||||
let previousBlock = chain[chain.count - 2]
|
||||
let timeSpent = Double(lastBlock.timestamp - previousBlock.timestamp)
|
||||
|
||||
if timeSpent < targetBlockTime / 2 {
|
||||
return min(lastBlock.difficulty + 1, maxDifficulty)
|
||||
} else if timeSpent > targetBlockTime * 2 {
|
||||
return max(lastBlock.difficulty - 1, minDifficulty)
|
||||
}
|
||||
|
||||
return lastBlock.difficulty
|
||||
}
|
||||
|
||||
/**
|
||||
Check validity of the blockchain.
|
||||
*/
|
||||
func chainValidity() {
|
||||
var isChainValid = true
|
||||
var corruptedBlock = Block()
|
||||
|
||||
for i in 1...chain.count-1 {
|
||||
if chain[i].previousHash != chain[i-1].hash {
|
||||
isChainValid = false
|
||||
corruptedBlock = chain[i]
|
||||
|
||||
func submitTransaction(_ transaction: Transaction) -> Bool {
|
||||
return memPool.addTransaction(transaction)
|
||||
}
|
||||
|
||||
func getBalance(address: String) -> Int {
|
||||
return accountManager.getBalance(address)
|
||||
}
|
||||
|
||||
func chainValidity() -> Bool {
|
||||
for i in 1..<chain.count {
|
||||
let currentBlock = chain[i]
|
||||
let previousBlock = chain[i-1]
|
||||
|
||||
if !currentBlock.isValid() || currentBlock.previousHash != previousBlock.hash {
|
||||
print("Chain invalid at block \(i)")
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
print("Chain is valid : \(isChainValid)")
|
||||
|
||||
if !isChainValid {
|
||||
print("Corrupted block is : \(corruptedBlock.index)")
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user