iOS 书写简单的区块链程序

字数 363阅读 1177

前言

区块链(Blockchain)是比特币等流行的加密货币背后的技术。区块链的主要概念是去中心化,提供分布式账本。本文会为你展示如何在 iOS/macOS 中使用 Swift 语言创建最基本的区块链。
注意:本文不涉及节点(nodes/peers)、验证和奖励等。


实现区块类

实现区块类,生成对象代表一个区块,创建如下:

//MARK: 区块
/// 简单模拟区块链,假设是单链的
class Block{
    var index : Int = 0          //区块所在节点
    var dateCreated  : String?   //区块产生时间
    var previousHash : String?  //前一个区块的hash
    var hash:String?   //hash值
    var nonce:Int = 0 //生成符合条件的hash值所需次数 -> 模拟难度值
    
     //模拟操作,保证key有值
    var key: String {
        get {
            return String(self.index)+self.dateCreated! + self.previousHash!+String(self.nonce)
        }
    }
    
    init() {
        self.dateCreated = Date().toString()
        self.nonce = 0
    }
}

实现区块链类

生成对象代表一个区块链,这个区块链需要一个区块来初始化自己,这个区块,成为创世块. 代码如下:

//MARK:- 区块链,假设是单链的(实际区块链要复杂的多)
class BlockChain {
    
    private (set)var blocks = [Block]()
    
    /// 初始化区块链
    ///
    /// - Parameter genesisiBlock: 区块
    init(genesisiBlock:Block) {
        //添加区块到区块链中
        addBlock(block: genesisiBlock)
    }
    
    /// 添加区块
    ///
    /// - Parameter block: 区块
    func addBlock(block:Block) {
        if blocks.isEmpty {
            //添加创世块
            //第一个区块没有hash
            block.previousHash = "0"
            block.hash = generateHash(block: block)
        }else{
            let previousBlock = getPreviousBlock()
            block.previousHash = previousBlock.hash
            block.index = blocks.count
            block.hash = generateHash(block: block)
        }
        blocks.append(block)
        displayBlock(block: block)
    }
    
    func getPreviousBlock() -> Block {
        return blocks[blocks.count-1]
    }
    
    func displayBlock(block:Block) {
        print("---第\(block.index)个区块")
        print("创建日期:\(String(describing: block.dateCreated!))")
        print("Nonce:\(block.nonce)")
        print("前一个区块的hash值:\(String(describing: block.previousHash!))")
        print("hash值:\(String(describing: block.hash!))\n\n\n\n")
    }
    
    //计算hash值
    private func generateHash(block:Block) ->String{
        //计算hash
        var hash = block.key.sha1Hash()
        //筛选算出来的hash值
        //假设限制条件是hash值末尾必须是"00"
        while !hash.hasSuffix("00") {
            block.nonce += 1
            hash = block.key.sha1Hash();
        }
        return hash;
        
    }
}

generateHash 函数负责生成唯一的哈希值并赋值给区块。但并不使用完全随机的哈希,而是需要以“00”开头(模拟增加难度,实际区块链,这个值可能一直不同的区块计算,也是不一样的)的特定哈希。这个概念叫做“工作量证明系统”。在实际中工作量证明系统的解法会更复杂,解决的人也会获得奖励(可能是额外的比特币,玩客币等等,看具体交易平台)。

核心算法

// MARK: - String 类扩展
extension String{
    func sha1Hash() -> String {
        let task = Process()//  OC中的NSTask
        //Linux命令
        // 执行路径  -> 设置 shell 脚本参数
        // shasum SHA校验
        task.launchPath = "/usr/bin/shasum"
        task.arguments = [] //包含的shell语句
        let inputPipe = Pipe()
        //字符串转化为data写入文件
        inputPipe.fileHandleForWriting.write(self.data(using: .utf8)!)//写入文件
        inputPipe.fileHandleForWriting.closeFile()//保存并关闭
        let outputPipe = Pipe()
        task.standardOutput = outputPipe //标准输出
        task.standardInput = inputPipe   //标准输入
        task.launch()
        
        let data = outputPipe.fileHandleForReading.readDataToEndOfFile()
        let hash = String(data: data, encoding: .utf8)!
        return hash.replacingOccurrences(of: "  -\n", with: "")
        
    }
}

扩展

// MARK: - Date 时间
extension Date{
    
    /// 获取当前时间,转化为字符串
    ///
    /// - Returns: 时间戳
    func toString() -> String {
        let formatter = DateFormatter();
        formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
        return formatter.string(from: self);
    }
}


全部源码可以复制全部源码直接粘贴到Mac Playground中,直接运行,或者创建Command Line Tool 把代码粘贴到main.swift文件里面

推荐阅读更多精彩内容