美文网首页
iOS 书写简单的区块链程序

iOS 书写简单的区块链程序

作者: sunny冲哥 | 来源:发表于2018-01-29 08:47 被阅读984次

    前言

    区块链(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文件里面

    相关文章

      网友评论

          本文标题:iOS 书写简单的区块链程序

          本文链接:https://www.haomeiwen.com/subject/smgtzxtx.html