diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/Blockchain.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/Blockchain.xcscheme new file mode 100644 index 0000000..31501f9 --- /dev/null +++ b/.swiftpm/xcode/xcshareddata/xcschemes/Blockchain.xcscheme @@ -0,0 +1,102 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.swiftpm/xcode/xcuserdata/vbodinaud.xcuserdatad/xcschemes/xcschememanagement.plist b/.swiftpm/xcode/xcuserdata/vbodinaud.xcuserdatad/xcschemes/xcschememanagement.plist index 5026709..670d047 100644 --- a/.swiftpm/xcode/xcuserdata/vbodinaud.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/.swiftpm/xcode/xcuserdata/vbodinaud.xcuserdatad/xcschemes/xcschememanagement.plist @@ -9,6 +9,27 @@ orderHint 0 + CryptoSwift (Playground) 1.xcscheme + + isShown + + orderHint + 2 + + CryptoSwift (Playground) 2.xcscheme + + isShown + + orderHint + 3 + + CryptoSwift (Playground).xcscheme + + isShown + + orderHint + 1 + SuppressBuildableAutocreation diff --git a/Package.resolved b/Package.resolved index 1dbca2c..ada42b9 100644 --- a/Package.resolved +++ b/Package.resolved @@ -6,8 +6,8 @@ "repositoryURL": "https://github.com/krzyzanowskim/CryptoSwift.git", "state": { "branch": null, - "revision": "a44caef0550c346e0ab9172f7c9a3852c1833599", - "version": "1.3.0" + "revision": "5669f222e46c8134fb1f399c745fa6882b43532e", + "version": "1.3.8" } } ] diff --git a/Package.swift b/Package.swift index 8ab9fcc..73f6be6 100644 --- a/Package.swift +++ b/Package.swift @@ -5,6 +5,9 @@ import PackageDescription let package = Package( name: "Blockchain", + platforms: [ + .macOS(.v10_12), + ], dependencies: [ // Dependencies declare other packages that this package depends on. // .package(url: /* package url */, from: "1.0.0"), diff --git a/Sources/Blockchain/Models/Block.swift b/Sources/Blockchain/Models/Block.swift index 50c0e72..5673a5c 100644 --- a/Sources/Blockchain/Models/Block.swift +++ b/Sources/Blockchain/Models/Block.swift @@ -17,6 +17,19 @@ class Block { var nonce: Int var timestamp: Int + /** + Initialize a block with the provided parts and specifications. + + - parameters: + - hash: The hash of the block + - data: The data of the block + - previousHash: The hash of the previous block + - index: The index of the block + - nonce: The nonce of the block + - timestamp: The timestamp of the block + + - returns: A beautiful new block for the blockchain. + */ init(hash: String = "", data: String = "", previousHash: String = "", index: Int = 0, nonce: Int = 0, timestamp: Int = 0) { self.data = data self.previousHash = previousHash @@ -26,10 +39,20 @@ class Block { self.hash = hash } + /** + Generate the hash of the block. + + - returns: The hash of the block + */ func generateHash() -> String { return data.sha256() } + /** + Generate the timestamp of the block + + - returns: The timestamp of the block + */ func generateTimestamp() -> Int { return Int(Date().timeIntervalSince1970) } diff --git a/Sources/Blockchain/Models/Blockchain.swift b/Sources/Blockchain/Models/Blockchain.swift index c19854e..f82add9 100644 --- a/Sources/Blockchain/Models/Blockchain.swift +++ b/Sources/Blockchain/Models/Blockchain.swift @@ -11,6 +11,12 @@ import Foundation class Blockchain { var chain = [Block]() + /** + Initialize the first block of the blockchain. + + - Parameters: + - data: The datas of the block + */ func createGenesisBlock(data: String) { let genesisBlock = Block() genesisBlock.data = data @@ -20,19 +26,63 @@ class Blockchain { genesisBlock.timestamp = genesisBlock.generateTimestamp() genesisBlock.hash = genesisBlock.generateHash() chain.append(genesisBlock) - print("Genesis block created -- hash: \(genesisBlock.hash ?? "")") + 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[chain.count-1].hash + 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 ?? 0) created -- hash: \(newBlock.hash ?? "") previous hash: \(newBlock.previousHash ?? "") data: \(newBlock.data ?? "")") + print("-- Block \(newBlock.index) created --\n hash: \(newBlock.hash)\n previous hash: \(newBlock.previousHash)\n data: \(newBlock.data)") + } + + /** + 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)") + } + + /** + 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] + } + } + + print("Chain is valid : \(isChainValid)") + + if !isChainValid { + print("Corrupted block is : \(corruptedBlock.index)") + } } } diff --git a/Sources/Blockchain/main.swift b/Sources/Blockchain/main.swift index 07965d5..8b369a1 100644 --- a/Sources/Blockchain/main.swift +++ b/Sources/Blockchain/main.swift @@ -17,16 +17,28 @@ repeat { print("Enter command:") command = readLine() + // Create a new block if command == "create" { print("data for the new block:") let data = readLine() blockchain.createBlock(data: data ?? "") } + // Create a lot of blocks if command == "spam" { for _ in 1...1000 { blockchain.createBlock(data: "\((blockchain.chain.last?.index ?? 0)+1)") } } + // Check validity of the blockchain + if command == "validity" { + blockchain.chainValidity() + } + + // Insert a corrupted block + if command == "corrupt" { + blockchain.insertCorruptedBlock() + } + } while command != "exit"