Trong demo này chúng ta sẽ cũng tìm hiểu khái quát về blockchain gồm các phần sau:
Tạo một blockchain cơ bản
Thực thi cơ bản về thuật toán(proof of work, mining)
Bạn cần hiểu về OOP, và với bài này mình dùng Swift.
Đầu tiên mình sẽ tạo project mới và đặt tên là NoobChain và class mới cũng có tên là NoobChain.
Tạo BlockChain
Như tên gọi của nó thì một blockchain giống như các block và được nối với nhau bới chain. Với mỗi block nó sẽ có chữ ký của nó và 1 chữ ký khác của thằng block trước nó và vài thông tin khác..
Ở đây hash chính là chữ ký.
Như đã nói thì một blockchain nó sẽ chứa 2 loại chữ ký là của nó và của thằng trước nó. Nếu dữ liệu của thằng trước nó thành đổi thì chữ ký của thằng trước nó cũng sẽ thay đổi vì chữ ký nó được tạo ra bởi một số các thông tin do mình quy định, điều đó nghĩa là khi 1 block thay đổi thì toàn bộ các block sau block đó phải thay đổi theo…
Tiếp theo tôi sẽ tạo 1 BlockChain
class Block
{
var hash:String!
var previousHash:String!
var data:String!
var timeStamp:Double!
init(data: String, previousHash: String) {
self.data = data
self.previousHash = previousHash
self.timeStamp = Date().timeIntervalSince1970
}
}
Tạo chữ ký cho blockchain
Có rất nhiều cách để mã hoá string nhưng trong bài này mình sẽ sử dụng SHA256, các bạn cần thêm CommonCrypto framework vào file bridging import
#import <CommonCrypto/CommonHMAC.h>
và thêm extension sau
extension String {
func sha256() -> String{
if let stringData = self.data(using: String.Encoding.utf8) {
return hexStringFromData(input: digest(input: stringData as NSData))
}
return ""
}
private func digest(input : NSData) -> NSData {
let digestLength = Int(CC_SHA256_DIGEST_LENGTH)
var hash = [UInt8](repeating: 0, count: digestLength)
CC_SHA256(input.bytes, UInt32(input.length), &hash)
return NSData(bytes: hash, length: digestLength)
}
private func hexStringFromData(input: NSData) -> String {
var bytes = [UInt8](repeating: 0, count: input.length)
input.getBytes(&bytes, length: input.length)
var hexString = ""
for byte in bytes {
hexString += String(format:"%02x", UInt8(byte))
}
return hexString
}
}
Tiếp theo tôi viết hàm calculateHash
func calculateHash() -> String{
return (previousHash! + "\(timeStamp)" + "\(nonce)" + data!).sha256()
}
và chỉnh lại hàm khởi tạo như sau:
init(data: String, previousHash: String) {
self.data = data
self.previousHash = previousHash
self.timeStamp = Date().timeIntervalSince1970
self.hash = self.calculateHash()
}
Bây giờ bạn có thể kiểm tra bằng cách tạo ra các blockChain như sau:
class NoobChain{
init() {
let block1 = Block.init(data: "First block", previousHash: "0")
let block2 = Block.init(data: "Second block", previousHash: block1.hash)
let block3 = Block.init(data: "Third block", previousHash: block2.hash)
print("Hash for block 1: \(block1.hash!)")
print("Hash for block 2: \(block2.hash!)")
print("Hash for block 3: \(block3.hash!)")
}
}
Khi chạy thì nó sẽ như sau:
Với mỗi block thì nó đã có chữ ký của nó và chữ ký của thằng trước nó
Tiếp theo tôi sẽ viết hàm kiểm tra mảng các blockchains mới tạo
func isChainValid(blocks: [Block]) -> Bool
{
var block1: Block!
var block2: Block!
for index in 1..<blocks.count{
block1 = blocks[index]
block2 = blocks[index - 1]
if(block1.hash != block2.hash){
print("Current hashes not equal")
return false
}
if(block1.previousHash != block2.previousHash){
print("Previous hashes not equal")
return false
}
}
return true
}
Với đoạn mã trên thì tôi sẽ kiểm tra toàn bộ các blockchains, nếu có bất kỳ thay đổi nào thì nó sẽ trả về false
Tạo Mining block
Trước tiên bạn cần thêm extension sau:
extension Int{
func generateDifficulty() -> String{
var result = ""
var index = self
while index > 0 {
index = index - 1
result = result + "0"
}
return result
}
}
extension String {
func substring(_ to: Int) -> String {
let start = index(startIndex, offsetBy: to)
return String(self[..<start])
}
}
Tôi tạo thêm 1 biến kiểu Int có tên nonce, biến này cũng sẽ được ghép vào hash:
func mineBlock(difficulty: Int){
let target = difficulty.generateDifficulty()
while (self.hash.substring(difficulty) != target) {
nonce = nonce + 1
self.hash = calculateHash()
}
}
Ở đây tôi để start là 0 nhưng trên thực tết thì nó sẽ random điểm start, ơ đây các bạn có thể test với độ phức tạp giá trị 2-6 nhưng trên thực tế con số này sẽ rất lớn có khi hơn cả max value của kiểu Int, ví dụ như thằng Litecoin thì độ phức tạp nó trên 400000. Tiếp theo các bạn gọi hàm mineBlock như sau
init() {
let block1 = Block.init(data: "First block", previousHash: "0")
block1.mineBlock(difficulty: 4)
let block2 = Block.init(data: "Second block", previousHash: block1.hash)
block2.mineBlock(difficulty: 4)
let block3 = Block.init(data: "Third block", previousHash: block2.hash)
block3.mineBlock(difficulty: 4)
print("Hash for block 1: \(block1.hash!)")
print("Hash for block 2: \(block2.hash!)")
print("Hash for block 3: \(block3.hash!)")
print(block1)
print(block2)
print(block3)
}
Chạy để xem kết quả. Với giá trị thấp thì các bạn sẽ mất khoảng vài giây.
Mã nguồn: https://github.com/tubeobeotu/Swift-Sample/tree/master/NoobChain
Cảm ơn các bạn đã đọc!
Khóa học lập trình iOS Swift cập nhật chương trình mới nhất năm 2018, iOS 11- swift 4.1
Bình luận