swift 实现区块链_swift的区块连货币 - CSDN
  • 点击上方“蓝色字”可关注我们!暴走时评:根据最近发布的报道,全球银行间金融电信协会(SWIFT)很快就会允许在基于DLT的平台上进行GPI支付。此前,SWIFT在1月和企...
        
    640?wx_fmt=png点击上方“蓝色字”可关注我们!







    640?wx_fmt=jpeg

    暴走时评:根据最近发布的报道,全球银行间金融电信协会(SWIFT)很快就会允许在基于DLT的平台上进行GPI支付。此前,SWIFT在1月和企业区块链平台R3合作推出了一个利用GPI实现贸易与电商平台的互联的新网关的概念验证。

    作者:Ana Alexandre  翻译:Maya

    根据最近发布的报道,全球银行间金融电信协会(SWIFT)将允许DLT技术公司使用其全球支付创新(GPI)平台。

    在报道中,SWIFT透露它很快就会允许在基于DLT的平台上进行GPI支付。据称,该产品可以增加储蓄对账,并促进抵押品的流动。

    在该公告之前,SWIFT在1月和企业区块链平台R3合作推出了一个利用GPI实现贸易与电商平台的互联的新网关的概念验证。该产品旨在将各种交易平台连接到GPI成员,允许端到端的支付跟踪,支付验证和信用确认。首席执行官Gottfried Leibbrandt当时表示:

    “我们的新GPI平台具有极强的互操作性和开放性,我们一直都能连接到其他网络… … 我们今天晚些时候会宣布使用R3区块链完成的交易方面概念验证,你可以在交易平台上发起付款,然后它会进入GPI。我们正在探索很多事情的互联性。”

    此前,SWIFT与主要金融机构(包括德意志银行、星展银行、汇丰银行、渣打银行、证券软件提供商SLI和新加坡交易所)进行了基于区块链的股东电子投票PoC。该测试旨在确定DLT是否可以简化股东大会的管理。

    此外,现有的SWIFT网络和基础设施也被用于获取,测试和验证该技术的适用性。

    本文仅代表作者个人观点,不代表区块链铅笔的立场,不构成投资建议,内容仅供参考。

    640?wx_fmt=png

    3分钟了解什么是区块链?(中文动画)|(英文动画教程

    3分钟了解什么是DAO?(中文动画)|(英文动画教程)

    3分钟看懂以太坊和智能合约?(中文动画)|(英语动画教程)

    3分钟了解比特币挖矿和区块链共识机制?(中文动画)|(英文动画教程)

    3分钟了解公有链和私有链(中文动画教程)|(英文动画教程)

    3分钟了解区块链的六层模型(中文动画教程)|(英文动画教程)

    什么是区块链英文版(动画教程)

    肖风:区块链与另类资产配置

    逐鹿区块链!详解三大巨头BAT区块链战略布局

    麦肯锡报告:区块链对保险行业的影响

    八张图表解读区块链的未来发展

    震惊全球的The DAO黑客事件全程回顾

    Circle获得包括IDG、百度、万向在内6000万美元融资


    关注本公众号后,进入公众号

    回复关键词可以查阅资料,以下是部分关键词


    回复 WEF ,查看《WEF:世界经济论坛认为区块链是互联网金融行业的未来报告》

    回复 智能合约 ,查看《巴克莱银行报告》

    回复 moody ,查看《穆迪120个区块链项目报告》

    回复 SWIFT ,查看SWIFT《区块链对证券交易全流程产生的影响及潜力》报告

    回复 论文11 ,查看论文《可扩展的去中心区块链》

    回复 埃森哲2 ,查看埃森哲《区块链每年可以为投资银行节省120亿美元》报告

    回复 联合国报告 ,查看联合国报告《数字货币和区块链技术在构建社会和可信金融之间扮演的角色》

    回复 用户特性 ,查看普林斯顿大学首本比特币教科书初稿《比特币用户的特性(Characteristics of Bitcoin Users)》

    回复 普林斯顿 ,查看普林斯顿大学首本比特币教科书初稿《比特币和数字货币技术(Bitcoin and Cryptocurrency Technologies)》

    回复 IMF,查看国际货币基金组织报告《Virtual Currencies and Beyond: Initial Considerations》

    回复 DTCC ,查看美国存管信托清算公司报告《DTCC: 拥抱分布式》

    回复 广发 ,查看报告《科技前沿报告:区块链:正快速走进公众和政策视野》

    回复 川财1 ,查看报告《川财证券:区块链技术调研报告之一:具有颠覆所有行业的可能性》

    回复 川财2 ,查看报告《川财证券:区块链技术调研报告之二:区块链技术进化论-区块链技术的国内实践和展望》

    回复 桑坦德 ,查看桑坦德银行报告《The Fintech 2.0 Paper: rebooting financial services》

    回复 拜占庭 ,查看《拜占庭将军问题详解》

    回复 论文1 ,查看论文《比特币闪电网络:可扩展的离线即时支付》

    回复 论文2 ,查看论文《比特币骨干协议》

    回复 论文3 ,查看论文《数字货币是否应该进入Barbados央行国际储备货币组合中》

    回复 帮助 ,查看本公众号全部关键词列表

    640?wx_fmt=jpeg

    点击下方“阅读原文”查看更多页面出现后再点击“来源”可以查看译文原文链接 ↓↓↓


    展开全文
  • 在这篇文章里会使用服务器端 Swift 框架 Vapor 在云端实现区块链。通过 HTTP 协议来构建区块链 Web API,使用不同的路由来提供必要的功能。阅读本文需要在电脑上安装 Vapor 框架(这个框架很牛逼 国外服务器不是用...

    最近火热的区块链 小编也不禁追赶一下潮流   无所谓什么开发语言 设计思路大同小异。

    下面讨论了如何用 Swift 语言实现基本的区块链。在这篇文章里会使用服务器端 Swift 框架 Vapor 在云端实现区块链。通过 HTTP 协议来构建区块链 Web API,使用不同的路由来提供必要的功能。阅读本文需要在电脑上安装 Vapor 框架(这个框架很牛逼 国外服务器不是用这个就是Python),还需要对 Swift 语言有基本的了解。

    实现模型

    第一步是为区块链 Web API 创建必要的模型,如下所示。

    Block:Block(区块)类表示一个区块,包含交易的输入和输出。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    class Block: Codable {
        var index: Int = 0
        var dateCreated: String
        var previousHash: String!
        var hash: String!
        var nonce: Int
        var message: String ""
        private (setvar transactions: [Transaction] = [Transaction]()
        var key: String {
            get {
                let transactionsData = try! JSONEncoder().encode(self.transactions)
                let transactionsJSONString = String(data: transactionsData, encoding: .utf8)
                return String(self.index) + self.dateCreated + self.previousHash + transactionsJSONString! + String(self.nonce)
            }
        }
        func addTransaction(transaction: Transaction) {
            self.transactions.append(transaction)
        }
        init() {
            self.dateCreated = Date().toString()
            self.nonce = 0
            self.message = "挖出新的区块"
        }
        init(transaction: Transaction) {
            self.dateCreated = Date().toString()
            self.nonce = 0
            self.addTransaction(transaction: transaction)
        }
    }

    Block 类的属性解释如下:

    • index——区块位于区块链中的位置。index 为 0 则表示该区块是区块链中的第一个区块。index 为 1 则表示区块链中的第二个区块……以此类推!

    • dateCreated——区块创建的日期

    • previousHash——前一个区块的哈希值

    • hash——当前区块的散列值

    • message——每个区块的备忘说明。只是为了例子使用

    • nonce——递增的数字,对生成哈希值很关键

    • transactions——一系列交易。每笔交易都代表货物/价值的转移

    • key——计算属性,提供给产生哈希值的函数

    Transaction:Transaction(交易)由 sender(发送者)、recipient(接收者)和被转移的 amount(金额)组成。实现如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    class Transaction: Codable {
        var from: String
        var to: String
        var amount: Double
        init(from: String, to: String, amount: Double) {
            self.from = from
            self.to = to
            self.amount = amount
        }
        init?(request: Request) {
            guard let from = request.data["from"]?.string, let to = request.data["to"]?.string, let amount = request.data["amount"]?.double else {
                return nil
            }
            self.from = from
            self.to = to
            self.amount = amount
        }
    }

    Transaction 类的实现很直观。由 from、to 和 amount 字段组成。为了简单起见,from 和 to 字段会用虚拟名字来表示,在实际中这两个字段还会包含包(wallet)ID 。

    Blockchain:Blockchain(区块链)类是表示区块列表的主类。每个区块都指向链中的前一个区块。每个区块可以包含多笔交易,表示信贷或借记。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    class Blockchain: Codable {
        var blocks: [Block] = [Block]()
        init() {
        }
        init(_ genesisBlock: Block) {
            self.addBlock(genesisBlock)
        }
        func addBlock(_ block: Block) {
            if self.blocks.isEmpty {
                // 添加创世区块
                // 第一个区块没有 previous hash
                block.previousHash = "0"
            else {
                let previousBlock = getPreviousBlock()
                block.previousHash = previousBlock.hash
                block.index = self.blocks.count
            }
            block.hash = generateHash(for: block)
            self.blocks.append(block)
            block.message = "此区块已添加至区块链"
        }
        private func getPreviousBlock() -> Block {
            return self.blocks[self.blocks.count - 1]
        }
        private func displayBlock(_ block: Block) {
            print("------ 第 \(block.index) 个区块 --------")
            print("创建日期:\(block.dateCreated)")
            // print("数据:\(block.data)")
            print("Nonce:\(block.nonce)")
            print("前一个区块的哈希值:\(block.previousHash!)")
            print("哈希值:\(block.hash!)")
        }
        private func generateHash(for block: Block) -> String {
            var hash = block.key.sha256()!
            // 设置工作量证明
            while(!hash.hasPrefix(DIFFICULTY)) {
                block.nonce += 1
                hash = block.key.sha256()!
                print(hash)
            }
            return hash
        }
    }

    每个模型都遵循 Codable 协议,以便转换为 JSON 对象。下一步是为 Web API 配置路由。

    使用 Vapor 实现 Web API

    有几种不同方式来用 Vapor 实现 Web API 。我在这里会创建一个自定义的控制器来处理所有区块链请求,这样就不用把所有代码都塞进 Routes 类里了。BlockchainController 实现如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    class BlockchainController {
        private (setvar drop: Droplet
        private (setvar blockchainService: BlockchainService!
        init(drop: Droplet) {
            self.drop = drop
            self.blockchainService = BlockchainService()
            // 为控制器设置路由
            setupRoutes()
        }
        private func setupRoutes() {
            self.drop.get("mine") { request in
                let block = Block()
                self.blockchainService.addBlock(block)
                return try JSONEncoder().encode(block)
            }
            // 添加新交易
            self.drop.post("transaction") { request in
                if let transaction = Transaction(request: request) {
                    // 添加交易至区块
                    // 获得最后一个挖出的区块
                    let block = self.blockchainService.getLastBlock()
                    block.addTransaction(transaction: transaction)
                    return try JSONEncoder().encode(block)
                }
                return try JSONEncoder().encode(["message""发生异常!"])
            }
            // 获得链
            self.drop.get("blockchain") { request in
                if let blockchain = self.blockchainService.getBlockchain() {
                    return try JSONEncoder().encode(blockchain)
                }
                return try! JSONEncoder().encode(["message":"区块链尚未初始化。请先挖矿"])
            }
        }
    }

    Web API 从三个基本的 endpoint 开始。

    • Mining(挖矿):这个 endpoint 会启动挖矿程序。挖矿可以让我们达到工作量证明,然后将区块添加到区块链。

    • Transaction:这个 endpoint 用于添加新交易。交易包含有关发送者、接收者和金额的信息。

    • Blockchain:这个 endpoint 返回完整的区块链。

    BlockchainController 使用 BlockChainService 来执行所需操作。BlockChainService 的实现如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    import Foundation
    import Vapor
    class BlockchainService {
         
        typealias JSONDictionary = [String:String]
        private var blockchain: Blockchain = Blockchain()
         
        init() {
        }
        func addBlock(_ block: Block) {
            self.blockchain.addBlock(block)
        }
        func getLastBlock() -> Block {
            return self.blockchain.blocks.last!
        }
        func getBlockchain() -> Blockchain? {
            return self.blockchain
        }
    }

    下面我们就来检查一下 Web API  的 endpoint。启动 Vapor 服务器然后发送请求到 “mine” endpoint。

    1.png

    工作量证明算法生成了以“000”开头的散列值。区块被挖出后就立即转换为 JSON 格式返回回来。通过 Swift 4.0 的 Codable 协议实现。

    现在给区块链添加一笔简单的交易,从张嘉夫那里转移10美元给马云。

    1.png

    最后一步是检查区块链是否含有新添加的区块。访问 “blockchain” endpoint 来查看完整的链。

    1.png

    完美!我们的区块链 Web API 现在可以正常工作了。

    还有一点遗憾的是,区块链应该是去中心化的,但目前我们没有添加新节点的机制。在下面我们会更新区块链实现以便让其支持多个节点。

    给区块链添加节点

    在给区块链添加节点之前,首先要定义节点。节点模型的实现如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    class BlockchainNode :Codable {
         
        var address :String
         
        init(address :String) {
            self.address = address
        }
         
        init?(request :Request) {
             
            guard let address = request.data["address"]?.string else {
                return nil
            }
             
            self.address = address
        }
         
    }

    BlockChainNode 类很简单,只有一个 address 属性,用于标识节点服务器的 URL。然后更新 BlockchainController 来添加注册新节点功能。如下所示:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    self.drop.get("nodes") { request in
                return try JSONEncoder().encode(self.blockchainService.getNodes())
            }
    self.drop.post("nodes/register") { request in
                guard let blockchainNode = BlockchainNode(request: request) else {
                    return try JSONEncoder().encode(["message""注册节点出现错误"])
                }
                 
                self.blockchainService.registerNode(blockchainNode)
                return try JSONEncoder().encode(blockchainNode)
            }

    还要更新 BlockchainService 以便注册新节点。

    1
    2
    3
    4
    5
    6
    7
      func getNodes() -> [BlockchainNode] {
            return self.blockchain.nodes
        }
         
        func registerNode(_ blockchainNode: BlockchainNode) {
            self.blockchain.addNode(blockchainNode)
        }

    下面来测试一下。启动新的 Vapor 服务器然后试着注册新节点。

    1.png

    节点注册好后,可以使用 nodes endpoint 来获取它,如下所示:

    1.png

    现在可以注册新节点了,下面要着重解决(resolve)节点间的冲突。如果某个节点上的区块链比其它节点的要大,就会产生冲突。在这种情况下,一般都是获得临近节点并用较大的区块链更新它们。

    解决节点间的冲突

    为了创建冲突,我们需要第二台服务器或是在另一个端口上运行服务器。本文会用后一种方法,在另一个端口上启动  Vapor 服务器。这两个节点初始化后,各创建一些区块和交易,这些区块会被添加到各自的区块链上。最后,调用 resolve endpoint 来解决节点间的冲突,并将节点更新为较大的那个区块链。

    给 BlockchainController 添加新的 endpoint 来解决冲突。

    1
    2
    3
    4
    5
    6
    7
    8
    self.drop.get("nodes/resolve") { request in
                return try Response.async { portal in
                    self.blockchainService.resolve { blockchain in
                        let blockchain = try! JSONEncoder().encode(blockchain)
                        portal.close(with: blockchain.makeResponse())
                    }
                }
            }

    上面使用了 Vapor 框架的 async  response 功能来异步处理响应。然后再更新 BlockchainService 来解决冲突。实现如下所示:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    func resolve(completion: @escaping(Blockchain) -> ()) {
            //获取节点
            let nodes = self.blockchain.nodes
             
            for node in nodes {
                let url = URL(string: "http://\(node.address)/blockchain")!
                URLSession.shared.dataTask(with: url, completionHandler: { (data, _, _) in
                    if let data = data {
                        let blockchain = try! JSONDecoder().decode(Blockchain.self, from: data)
                         
                        if self.blockchain.blocks.count > blockchain.blocks.count {
                            completion(self.blockchain)
                        else {
                            self.blockchain.blocks = blockchain.blocks
                            completion(blockchain)
                        }
                    }
                }).resume()
            }
        }

    resolve 函数遍历节点列表并获取每个节点的区块链。如果某个区块链比当前区块链要大,则替换当前区块链为更大的那个,否则直接返回当前区块链,因为当前区块链已经是更大的区块链了。

    为了测试我们要在不同的端口开启两台服务器,在 8080 端口上添加三笔交易,在 8081 上添加两笔。可以在终端里输入下面的命令来启动 Vapor 服务器。

    1
    vapor run serve -—port=8081

    在 8080 端口上添加三笔交易,如下所示:

    1.png

    然后在 8081 端口节点上添加两笔交易,如下所示:

    1.png

    确保注册了 8080 地址的节点,如下所示:

    1.png

    最后,来一下测试 resolve endpoint。在 Postman 里访问 “resolve” endpoint,如下所示:

    1.png

    可以看到,resolve endpoint 返回了更大的区块链,同时也更新了节点的区块链。这样解决冲突方案就完工了。

    展开全文
  • 关键时刻,第一时间送达!...在这篇文章里会使用服务器端 Swift 框架 Vapor 在云端实现区块链。通过 HTTP 协议来构建区块链 Web API,使用不同的路由来提供必要的功能。阅读本文需要在电脑上安装 https://vapor.
        

    关键时刻,第一时间送达!

    640?

    640?wx_fmt=gif


    本文参考


    • http://www.wanbizu.com/baike/201408081395.html


    我在上一篇文章中讨论了如何用 Swift 语言实现基本的区块链。在这篇文章里会使用服务器端 Swift 框架 Vapor 在云端实现区块链。通过 HTTP 协议来构建区块链 Web API,使用不同的路由来提供必要的功能。阅读本文需要在电脑上安装 https://vapor.codes/ 框架,还需要对 Swift 语言有基本的了解。


    实现模型


    第一步是为区块链 Web API 创建必要的模型,如下所示。


    Block:Block(区块)类表示一个区块,包含交易的输入和输出。


    class Block: Codable {

        var index: Int = 0

        var dateCreated: String

        var previousHash: String!

        var hash: String!

        var nonce: Int

        var message: String = ""

        private (set) var transactions: [Transaction] = [Transaction]()


        var key: String {

            get {

                let transactionsData = try! JSONEncoder().encode(self.transactions)

                let transactionsJSONString = String(data: transactionsData, encoding: .utf8)


                return String(self.index) + self.dateCreated + self.previousHash + transactionsJSONString! + String(self.nonce)

            }

        }


        func addTransaction(transaction: Transaction) {

            self.transactions.append(transaction)

        }


        init() {

            self.dateCreated = Date().toString()

            self.nonce = 0

            self.message = "挖出新的区块"

        }


        init(transaction: Transaction) {

            self.dateCreated = Date().toString()

            self.nonce = 0

            self.addTransaction(transaction: transaction)

        }

    }


    Block 类的属性解释如下:


    • index——区块位于区块链中的位置。index 为 0 则表示该区块是区块链中的第一个区块。index 为 1 则表示区块链中的第二个区块……以此类推!

    • dateCreated——区块创建的日期

    • previousHash——前一个区块的哈希值

    • hash——当前区块的散列值

    • message——每个区块的备忘说明。只是为了例子使用

    • nonce——递增的数字,对生成哈希值很关键

    • transactions——一系列交易。每笔交易都代表货物/价值的转移

    • key——计算属性,提供给产生哈希值的函数


    Transaction:Transaction(交易)由 sender(发送者)、recipient(接收者)和被转移的 amount(金额)组成。实现如下:


    class Transaction: Codable {

        var from: String

        var to: String

        var amount: Double


        init(from: String, to: String, amount: Double) {

            self.from = from

            self.to = to

            self.amount = amount

        }


        init?(request: Request) {

            guard let from = request.data["from"]?.string, let to = request.data["to"]?.string, let amount = request.data["amount"]?.double else {

                return nil

            }

            self.from = from

            self.to = to

            self.amount = amount

        }

    }


    Transaction 类的实现很直观。由 from、to 和 amount 字段组成。为了简单起见,from 和 to 字段会用虚拟名字来表示,在实际中这两个字段还会包含包(wallet)ID 。


    Blockchain:Blockchain(区块链)类是表示区块列表的主类。每个区块都指向链中的前一个区块。每个区块可以包含多笔交易,表示信贷或借记。


    class Blockchain: Codable {

        var blocks: [Block] = [Block]()


        init() {


        }


        init(_ genesisBlock: Block) {

            self.addBlock(genesisBlock)

        }


        func addBlock(_ block: Block) {

            if self.blocks.isEmpty {

                // 添加创世区块

                // 第一个区块没有 previous hash

                block.previousHash = "0"

            } else {

                let previousBlock = getPreviousBlock()

                block.previousHash = previousBlock.hash

                block.index = self.blocks.count

            }


            block.hash = generateHash(for: block)

            self.blocks.append(block)

            block.message = "此区块已添加至区块链"

        }


        private func getPreviousBlock() -> Block {

            return self.blocks[self.blocks.count - 1]

        }


        private func displayBlock(_ block: Block) {

            print("------ 第 (block.index) 个区块 --------")

            print("创建日期:(block.dateCreated)")

            // print("数据:(block.data)")

            print("Nonce:(block.nonce)")

            print("前一个区块的哈希值:(block.previousHash!)")

            print("哈希值:(block.hash!)")

        }


        private func generateHash(for block: Block) -> String {

            var hash = block.key.sha256()!


            // 设置工作量证明

            while(!hash.hasPrefix(DIFFICULTY)) {

                block.nonce += 1

                hash = block.key.sha256()!

                print(hash)

            }


            return hash

        }

    }


    每个模型都遵循 Codable 协议,以便转换为 JSON 对象。如果你看了上一篇文章的话,上面的实现方式就很眼熟了。下一步是为 Web API 配置路由,后面一节会用 Vapor 框架来实现。


    使用 Vapor 实现 Web API


    有几种不同方式来用 Vapor 实现 Web API 。我在这里会创建一个自定义的控制器来处理所有区块链请求,这样就不用把所有代码都塞进 Routes 类里了。BlockchainController 实现如下:


    class BlockchainController {

        private (set) var drop: Droplet

        private (set) var blockchainService: BlockchainService!


        init(drop: Droplet) {

            self.drop = drop

            self.blockchainService = BlockchainService()


            // 为控制器设置路由

            setupRoutes()

        }


        private func setupRoutes() {

            self.drop.get("mine") { request in

                let block = Block()

                self.blockchainService.addBlock(block)

                return try JSONEncoder().encode(block)

            }


            // 添加新交易

            self.drop.post("transaction") { request in

                if let transaction = Transaction(request: request) {

                    // 添加交易至区块


                    // 获得最后一个挖出的区块

                    let block = self.blockchainService.getLastBlock()

                    block.addTransaction(transaction: transaction)


                    return try JSONEncoder().encode(block)

                }

                return try JSONEncoder().encode(["message": "发生异常!"])

            }


            // 获得链

            self.drop.get("blockchain") { request in

                if let blockchain = self.blockchainService.getBlockchain() {

                    return try JSONEncoder().encode(blockchain)

                }


                return try! JSONEncoder().encode(["message":"区块链尚未初始化。请先挖矿"])

            }

        }

    }


    Web API 从三个基本的 endpoint 开始。


    • Mining(挖矿):这个 endpoint 会启动挖矿程序。挖矿可以让我们达到工作量证明,然后将区块添加到区块链。

    • Transaction:这个 endpoint 用于添加新交易。交易包含有关发送者、接收者和金额的信息。

    • Blockchain:这个 endpoint 返回完整的区块链。


    BlockchainController 使用 BlockChainService 来执行所需操作。BlockChainService 的实现如下:


    import Foundation

    import Vapor


    class BlockchainService {

        

        typealias JSONDictionary = [String:String]

        private var blockchain: Blockchain = Blockchain()

        

        init() {


        }


        func addBlock(_ block: Block) {

            self.blockchain.addBlock(block)

        }


        func getLastBlock() -> Block {

            return self.blockchain.blocks.last!

        }


        func getBlockchain() -> Blockchain? {

            return self.blockchain

        }

    }


    下面我们就来检查一下 Web API  的 endpoint。启动 Vapor 服务器然后发送请求到 “mine” endpoint。


    640?wx_fmt=png


    工作量证明算法生成了以“000”开头的散列值。区块被挖出后就立即转换为 JSON 格式返回回来。通过 Swift 4.0 的 Codable 协议实现。

    现在给区块链添加一笔简单的交易,从张嘉夫那里转移10美元给马云。


    640?wx_fmt=other


    最后一步是检查区块链是否含有新添加的区块。访问 “blockchain” endpoint 来查看完整的链。


    640?wx_fmt=other


    完美!我们的区块链 Web API 现在可以正常工作了。


    还有一点遗憾的是,区块链应该是去中心化的,但目前我们没有添加新节点的机制。在下一节我们会更新区块链实现以便让其支持多个节点。


    给区块链添加节点


    在给区块链添加节点之前,首先要定义节点。节点模型的实现如下:


    class BlockchainNode :Codable {

        

        var address :String

        

        init(address :String) {

            self.address = address

        }

        

        init?(request :Request) {

            

            guard let address = request.data["address"]?.string else {

                return nil

            }

            

            self.address = address

        }

        

    }


    BlockChainNode 类很简单,只有一个 address 属性,用于标识节点服务器的 URL。然后更新 BlockchainController 来添加注册新节点功能。如下所示:


    self.drop.get("nodes") { request in

                return try JSONEncoder().encode(self.blockchainService.getNodes())

            }


    self.drop.post("nodes/register") { request in

                guard let blockchainNode = BlockchainNode(request: request) else {

                    return try JSONEncoder().encode(["message": "注册节点出现错误"])

                }

                

                self.blockchainService.registerNode(blockchainNode)

                return try JSONEncoder().encode(blockchainNode)

            }


    还要更新 BlockchainService 以便注册新节点。


      func getNodes() -> [BlockchainNode] {

            return self.blockchain.nodes

        }

        

        func registerNode(_ blockchainNode: BlockchainNode) {

            self.blockchain.addNode(blockchainNode)

        }


    下面来测试一下。启动新的 Vapor 服务器然后试着注册新节点。


    640?wx_fmt=other


    节点注册好后,可以使用 nodes endpoint 来获取它,如下所示:


    640?wx_fmt=other


    现在可以注册新节点了,下面要着重解决(resolve)节点间的冲突。如果某个节点上的区块链比其它节点的要大,就会产生冲突。在这种情况下,一般都是获得临近节点并用较大的区块链更新它们。


    解决节点间的冲突


    为了创建冲突,我们需要第二台服务器或是在另一个端口上运行服务器。本文会用后一种方法,在另一个端口上启动  Vapor 服务器。这两个节点初始化后,各创建一些区块和交易,这些区块会被添加到各自的区块链上。最后,调用 resolve endpoint 来解决节点间的冲突,并将节点更新为较大的那个区块链。

    给 BlockchainController 添加新的 endpoint 来解决冲突。


    self.drop.get("nodes/resolve") { request in

                return try Response.async { portal in

                    self.blockchainService.resolve { blockchain in

                        let blockchain = try! JSONEncoder().encode(blockchain)

                        portal.close(with: blockchain.makeResponse())

                    }

                }

            }


    上面使用了 Vapor 框架的 async  response 功能来异步处理响应。然后再更新 BlockchainService 来解决冲突。实现如下所示:


    func resolve(completion: @escaping(Blockchain) -> ()) {

            //获取节点

            let nodes = self.blockchain.nodes

            

            for node in nodes {

                let url = URL(string: "http://(node.address)/blockchain")!

                URLSession.shared.dataTask(with: url, completionHandler: { (data, _, _) in

                    if let data = data {

                        let blockchain = try! JSONDecoder().decode(Blockchain.self, from: data)

                        

                        if self.blockchain.blocks.count > blockchain.blocks.count {

                            completion(self.blockchain)

                        } else {

                            self.blockchain.blocks = blockchain.blocks

                            completion(blockchain)

                        }

                    }

                }).resume()

            }

        }


    resolve 函数遍历节点列表并获取每个节点的区块链。如果某个区块链比当前区块链要大,则替换当前区块链为更大的那个,否则直接返回当前区块链,因为当前区块链已经是更大的区块链了。

    为了测试我们要在不同的端口开启两台服务器,在 8080 端口上添加三笔交易,在 8081 上添加两笔。可以在终端里输入下面的命令来启动 Vapor 服务器。


    vapor run serve -—port=8081


    在 8080 端口上添加三笔交易,如下所示:


    640?wx_fmt=other


    然后在 8081 端口节点上添加两笔交易,如下所示:


    640?wx_fmt=other


    确保注册了 8080 地址的节点,如下所示:


    640?wx_fmt=other


    最后,来一下测试 resolve endpoint。在 Postman 里访问 “resolve” endpoint,如下所示:


    640?wx_fmt=other


    可以看到,resolve endpoint 返回了更大的区块链,同时也更新了节点的区块链。这样解决冲突方案就完工了。


    [GitHub](https://github.com/josephchang10/Blockchain-Web-API)



    640?

    • 作者:张嘉夫_Joseph

    • 链接:https://juejin.im/post/5a48f645f265da43310e2a30

    • iOS开发整理发布,转载请联系作者授权

    640?wx_fmt=gif

    640?【点击成为Android大神】

    展开全文
  • Swift Playgrounds中实现简单区块链,主要用于学习
  • SwiftyEOS是一个用于与EOS交互的开源框架,用Swift编写。可以在iOS和macOS上使用。 特点: EOS密钥对生成 私钥导入 签名哈希 基本的RPC API(链/历史)可查询客户端 交易(EOS token 转账) 帮助类处理iOS上的脱机...

    SwiftyEOS是一个用于与EOS交互的开源框架,用Swift编写。可以在iOS和macOS上使用。

    特点:

    • EOS密钥对生成
    • 私钥导入
    • 签名哈希
    • 基本的RPC API(链/历史)可查询客户端
    • 交易(EOS token 转账)
    • 帮助类处理iOS上的脱机钱包
    • 在iOS上加密/解密导入私钥

    如何使用它

    • 1.将LibrariesSources文件夹复制到项目中,不需要main.swift
    • 2.如果不是针对iOS平台,请删除Sources/Utils/iOS
    • 3.将Libraries/include添加到Header搜索路径中。
    • 4.将Libraries/include/Bridging-Header.h设置为Objective-C Bridging Header。如果你有自己的bridging header,请复制该文件中的所有导入内容并粘贴到你自己的文件中。
    • 5.编译然后等结果

    密钥对生成

    SwiftyEOS现在支持secp256k1密钥对。

    secp256r1密钥对生成有bug但我无法弄清楚原因。从cleos创建的单元测试创建密钥--r1不会通过。你可能不会将secp256r1视为一个选项,因为cleos wallet命令也无法导入这些键。

    生成随机密钥对:

    let (pk, pub) = generateRandomKeyPair(enclave: .Secp256k1)
    

    很容易对吧?

    print("private key: \(pk!.wif())")
    print("public key : \(pub!.wif())")
    
    // private key: PVT_K1_5HxrYTdZX89zodtJhTzCk87MfNZAkiBRfFvSX8kacYjtwaDpTkL
    // public key : PUB_K1_4yDYdmcVcXxAxeNsUWRG7x9FKQE4HbJZdzgZFv1AYxk6oSVcLd
    

    PVT_K1_PUB_K1_前缀是标准密钥表示的一部分。但是EOS系统和SwiftyEOS也支持旧方式:

    print("private key: \(pk!.rawPrivateKey())")
    print("public key : \(pub!.rawPublicKey())")
    
    // private key: 5HxrYTdZX89zodtJhTzCk87MfNZAkiBRfFvSX8kacYjtwaDpTkL
    // public key : EOS4yDYdmcVcXxAxeNsUWRG7x9FKQE4HbJZdzgZFv1AYxk6oSVcLd
    

    导入现有密钥:

    let importedPk = try PrivateKey(keyString: "5HxrYTdZX89zodtJhTzCk87MfNZAkiBRfFvSX8kacYjtwaDpTkL")
    let importedPub = PublicKey(privateKey: importedPk!)
    

    带分隔符和前缀:

    let importedPk = try PrivateKey(keyString: "PVT_K1_5HxrYTdZX89zodtJhTzCk87MfNZAkiBRfFvSX8kacYjtwaDpTkL")
    let importedPub = PublicKey(privateKey: importedPk!)
    

    RPC API

    EOSRPC.sharedInstance.chainInfo { (chainInfo, error) in
        if error == nil {
            print("Success: \(chainInfo!)")
        } else {
            print("Error: \(error!.localizedDescription)")
        }
    }
    

    目前我们有一些基本的RPC端点,你可以在Sources/SwiftyEOS/Network找到它。

    iOS的密钥存储

    我们有SEWallet.swift iOS版离线钱包管理助手。

    SEWallet.swift可以方便地保存AES加密的密钥信息到文件系统。默认位置是应用程序的沙盒。

    目前还不支持多个钱包管理。

    在iOS上创建新钱包

    在Objective-C中:

    [SEKeystoreService.sharedInstance newAccountWithPasscode:passcode succeed:^(SELocalAccount *account) {
    } failed:^(NSError *error) {
            
    }];
    

    检索已保存的钱包

    [SELocalAccount currentAccount];
    

    如果没有保存钱包,它将返回零。

    交易

    交易行为目前尚未完全支持,但你仍可以尝试使用main.swift中的示例代码。

    整个功能完成后,将提供相关文件。

    • 货币转账(2018.08.15)
    • 提交一般交易(2018.08.16)
    • iOS上的设备上(离线)钱包锁定和解锁(2018.08.17)
    • 押注/取消押注/净值(2018.08.28)
    • 买/卖ram(2018.08.28)
    • 创建账户(2018.10)
    • 用params列表推送交易(2018.11.05)
    • 使用助记符创建/导入密钥对

    货币转账

    var transfer = Transfer()
    transfer.from = "agoodaccount"
    transfer.to = "gq3dinztgage"
    transfer.quantity = "1.0000 EOS"
    transfer.memo = "eureka"
    
    Currency.transferCurrency(transfer: transfer, code: "eosio.token", privateKey: importedPk!, completion: { (result, error) in
        if error != nil {
            if error is RPCErrorResponse {
                print("\((error as! RPCErrorResponse).errorDescription())")
            } else {
                print("other error: \(String(describing: error?.localizedDescription))")
            }
        } else {
            print("done.")
        }
    })
    

    提交一般交易

    swift:

    let account = "raoji"
    let asset = "1.0000 EPRA"
    
    let data = "{\"hey\": {\"account\":\"" + account  + "\", \"quantity\":\"" + asset + "\"}}"
    let abi = try! AbiJson(code: "prabox1", action: "withdraw", json: data)
    
    TransactionUtil.pushTransaction(abi: abi, account: account, privateKey: importedPk!, completion: { (result, error) in
        if error != nil {
            if (error! as NSError).code == RPCErrorResponse.ErrorCode {
                print("\(((error! as NSError).userInfo[RPCErrorResponse.ErrorKey] as! RPCErrorResponse).errorDescription())")
            } else {
                print("other error: \(String(describing: error?.localizedDescription))")
            }
        } else {
            print("Ok. Txid: \(result!.transactionId)")
        }
    })
    

    Objective-C:

    AbiJson *your_abi;
    [TransactionUtil pushTransactionWithAbi:your_abi
                                    account:@"your_account"
                                   pkString:@"your_private_key"
                                 completion:^(TransactionResult *result, NSError *error) {
            
    }];
    

    iOS上的设备上(离线)钱包锁定和解锁

    我们添加locktimedUnlock函数到SELocalAccount

    Cpu/net/ram 操作

    ResourceUtil.swift文件包括ResourceUtil类,包括下面几个方法:

    • stakeResource
    • unstakeResource
    • buyRam
    • sellRam

    Stake resource:

    ResourceUtil.stakeResource(account: "raoji", net: 1.0, cpu: 1.0, pkString: "5HsaHvRCPrjU3yhapB5rLRyuKHuFTsziidA13Uw6WnQTeJAG3t4", completion: { (result, error) in
    })
    

    助记符

    建一个新的密钥对:

    let (pk, pub, mn) = generateRandomKeyPair(enclave: .Secp256k1)
    

    导入现有助记符:

    let (pk, mn) = PrivateKey(enclave: .Secp256k1, mnemonicString: "your words here")
    

    我们在SEWallet.swift中有密钥管理的iOS助手API和助记符。现在可以使用SEKeystoreService类创建和导入助记符(如果你自己存储,则可以使用SEKeystore更深入的API):

    SEKeystoreService.sharedInstance.newAccountAndMnemonic(passcode: "your pass here", succeed: { (account, mnemonic) in
    
    }) { (error) in
    
    }
    

    我们正在为所有顶级API使用NSObject固有类,因此在不提供额外桥接文件的情况下调用Objective-C也是一样的。

    SEWallet.swift文件中也有iOS的帮助方法。

    谢谢。

    ======================================================================

    分享一些以太坊、EOS、比特币等区块链相关的交互式在线编程实战教程:

    • EOS教程,本课程帮助你快速入门EOS区块链去中心化应用的开发,内容涵盖EOS工具链、账户与钱包、发行代币、智能合约开发与部署、使用代码与智能合约交互等核心知识点,最后综合运用各知识点完成一个便签DApp的开发。
    • java以太坊开发教程,主要是针对java和android程序员进行区块链以太坊开发的web3j详解。
    • python以太坊,主要是针对python工程师使用web3.py进行区块链以太坊开发的详解。
    • php以太坊,主要是介绍使用php进行智能合约开发交互,进行账号创建、交易、转账、代币开发以及过滤器和交易等内容。
    • 以太坊入门教程,主要介绍智能合约与dapp应用开发,适合入门。
    • 以太坊开发进阶教程,主要是介绍使用node.js、mongodb、区块链、ipfs实现去中心化电商DApp实战,适合进阶。
    • C#以太坊,主要讲解如何使用C#开发基于.Net的以太坊应用,包括账户管理、状态与交易、智能合约开发与交互、过滤器和交易等。
    • java比特币开发教程,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Java代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是Java工程师不可多得的比特币开发学习课程。
    • php比特币开发教程,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Php代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是Php工程师不可多得的比特币开发学习课程。
    • tendermint区块链开发详解,本课程适合希望使用tendermint进行区块链开发的工程师,课程内容即包括tendermint应用开发模型中的核心概念,例如ABCI接口、默克尔树、多版本状态库等,也包括代币发行等丰富的实操代码,是go语言工程师快速入门区块链开发的最佳选择。

    汇智网原创翻译,转载请标明出处。这里是原文Swift编写的EOS开源框架SwiftyEOS

    展开全文
  • 在 iOS 中实现区块链

    2018-02-04 09:59:33
    本文会为你展示如何在 iOS/macOS 中使用 Swift 语言创建最基本的区块链。注意:本文不涉及节点(nodes/peers)、验证和奖励等。我会用 macOS Playground 来演示,快且方便,还有一些实用的函数可以用来生成 SHA 哈希...
  • SwiftLightning是Swift 实现的 Lighting Networking(易于扩展、跨区块链即时(高速)支付网络)
  • 菜鸟与天猫国际27日宣布,已经启用区块链技术跟踪、上传、查证跨境进口商品的物流全链路信息。此外,蚂蚁金服已经将区块链技术用在公益、食品安全溯源上。蚂蚁技术实验室预测,2018年区块链技术将开始落地实际商用...
  • 点击上方“蓝色字”可关注我们!暴走时评:英格兰央行宣布,英格兰银行正计划重建实时全额结算(RTGS)系统,以便与使用分布式账本技术(DLT)的私人企业和平台进行交互。作者...
  • HPB钱包Xcode集成

    2019-04-15 09:30:28
    熟悉以太坊的朋友都知道,以太坊提供了一个Web3.js API 中文文档的库,通过调用js的代码去实现区块链DApp的开发。 但是对于iOS的小伙伴来说,直接调用js无疑是很困难的,并且从实现上来说也很复杂。因此我们找到了...
  • 暴走时评:个人碳交易公司CarbonX正在与区块链创业公司ConsenSys合作开发一个P2P碳信用交易平台。CarbonX希望能够通过该项目激励有利于环境可持续发展的行为,调动起群众的积极性来对抗环境变化带来的不利影响,同时...
  • 由于SWIFT是服务于金融机构的,因此必须在确保安全与可靠和稳定的情况下,才会向客户推出。 风靡IT、金融甚至能源领域的区块链技术,真的会颠覆现有的全球跨境支付体系吗?起码目前全球大多数国家、大多数银行在跨境...
  • 点击上方“蓝色字”可关注我们!暴走时评:云软件巨头Salesforce表示,希望在明年九月之前把区块链和加密货币整合到公司产品中。关于未来具体的实施,公司并没有详细计划,...
  • 以比特币网络为代表的大规模数字货币系统,长时间自治运行,支持了传统金融系统都难以实现的全球范围即时可靠交易。这为区块链技术的应用潜力引发了无限遐想。如果未来基于区块链技术构造的商业价值网络成为现实,...
  • 通过此篇博客,自己对“区块链”技术有了大致的了解,此篇博文讲的特别透彻,在此表示感谢~前言  最近区块链比较火,区块链是什么鬼,怎么以前没听过,不过说个东西你一定听过-比特币,以前区块链用在比特币上,...
  • 当前,区块链概念在我国已经逐渐火热起来,凭借其去中心化、无需中心信任、不可篡改和加密安全的特点已经逐 渐走入政府机构、金融领域以及诸多大型企业的视野。2016年10月18日,中国区块链技术和产业发展论坛成立...
1 2 3 4 5 ... 20
收藏数 2,656
精华内容 1,062
关键字:

swift 实现区块链