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