精华内容
下载资源
问答
  • 如何给区块链写SDK

    2020-04-30 10:26:18
    区块链开发完毕,需要通过SDK给其他开发者予以调用,所以SDK是降低区块链使用门槛必要的手段。 开发SDK的技术逻辑就是,通过离线构造包括签名在内的多种区块链交易,然后通过网络服务将交易数据发送到区块链...

    区块链开发完毕,需要通过SDK给其他开发者予以调用,所以SDK是降低区块链使用门槛必要的手段。

     

     

    开发SDK的技术逻辑就是,通过离线构造包括签名在内的多种区块链交易,然后通过网络服务将交易数据发送到区块链节点,区块链节点监听交易并执行符合规则交易。

     

     

    就以我开发的JS SDK为例,我在开发中实现以下功能:

     

    1.离线钱包功能

     

    1.1 实现钱包账户生成,包括助记词生成,公私钥生成,公钥转地址,keystore文件生成。

     

    1.2 账户交易签名和验证,构造交易,对交易进行离线签名和验证。

     

    1.3 账户转账,在不同账户之间形成资产转移。

     

    2.共识功能

     

    2.1 资源抵押和解冻

     

    2.2 设置代表和投票

     

    2.3 获得最新的代表和候选代表

     

    3.合约功能

     

    3.1 合约上链,实例化,调用,停用。

     

    3.2 相关合约模版搜索,实现个性化合约定制

     

    4.区块链管理功能

     

    4.1 查询最新交易,最新高度,最新代表

     

    4.2 获得交易,区块,当前节点,连接节点

     

    4.3 当前区块链网络

     

    5.特殊功能调用

     

    5.1区块链特殊合约,譬如USDT合约安全调用

     

    5.2 基本配置,例如Baas服务配置,节点配置等用于初始化连接区块链服务。

     

     

    其他语言SDK都类似,开发的难点其实不在逻辑,而在于对语言的掌握,如何用不同的语言,调用相同功能,实现一致效果。例如最基本的secp256k1曲线加密算法,Go SDK我依赖比特币的Go版本,同时在地址生成加上了一些自己的设计,而在nodejs中,我使用eccrypto椭圆曲线加密库,这个就比较基础,需要专门进行修改,以符合比特币中的规定。

    展开全文
  • 手把手带你复现AI+区块链写码全过程!(附代码&视频) 技术小能手 2018-02-24 13:16:32 浏览1031 评论1 云栖社区  python  分布式  算法  人工智能 摘要: 比特币的剧烈震荡,引起全民关注...

    点击有惊喜


    1. 云栖社区>
    2. 数据派THU>
    3. 博客>
    4. 正文

    手把手带你复现AI+区块链写码全过程!(附代码&视频)

    技术小能手 2018-02-24 13:16:32 浏览1031 评论1

    摘要: 比特币的剧烈震荡,引起全民关注,加快了区块链的普及速度。 区块链养猫养狗、区块链游戏、区块链游戏,区块链旅游……打着区块链名头的项目蜂拥上线。 如何将区块链和 AI 两种不同技术结合?如何在python中编写工作证明算法?一致性算法有哪些? 在这个视频中,我们重点讨论 AI+BlockChain 如何一起工作,如何在 python 中编写工作证明算法,然后在高层次上讨论一些其他的共识算法。

    9b55cfd2fe61ef0848421cfbf645ddb6bbcbf2e7

    比特币的剧烈震荡,引起全民关注,加快了区块链的普及速度。

    区块链养猫养狗、区块链游戏、区块链游戏,区块链旅游……打着区块链名头的项目蜂拥上线。

    如何将区块链和 AI 两种不同技术结合?如何在python中编写工作证明算法?一致性算法有哪些?

    在这个视频中,我们重点讨论 AI+BlockChain 如何一起工作,如何在 python 中编写工作证明算法,然后在高层次上讨论一些其他的共识算法。

    人工智能可以利用区块链的力量对数据进行审计,对其目标进行激励,甚至创造新型的精英组织。

    下面用图文给大家简单介绍视频中所提到的四种算法:

    ca84129db91a82cbdae92329726a5557124a392b

    币圈所用的 Consensus Algorithms(分布式一致性算法)主要有Proof of work (工作证明)算法和 Proof of Stake(权益证明)算法两种。

    Proof of work(工作证明)

    比特币交易的运行原理就是 Proof of work,我们有网络上所有交易的分布式账本,在每个矿工的计算机上都存有一个副本,一旦涉及确认交易时,他们都必须提供这个 Proof of work,他们已经计算出这个随机数学问题,只有这样做才能对交易进行确认。

    比特币的运作步骤是:交易验证→生成代码→周知其它矿工→如果大部分人都同意,交易将添加至区块链。矿工能挖到矿的概率取决于矿工做了多少工作,所以我们看到,比特币矿工的支出变得越来越小,矿工们会因为比特币供应量有限而加班减薪。

    Proof of stake(权益证明)

    Proof of stake 的原理则是,一个人的能力无关工作能力,而取决于他有多少币,拥有的币越多投票权越大;交易系统能够让51%以上的攻击成本变高;大部分的矿工都在努力采矿,以扩大比特币社区,但是比特币却集中在越来越少的人手里。

    任何人都可以通过发送,一种特殊类型的交易来锁定手持币成为存款,然后通过所有当前验证者可以参与的一致性算法,来完成和同意新区块的建立。

    Proof of Activity(活动证明)

    活动证明作为一种 Proof of work 和 Proof of stake 的混合证明,它一开始作为Proof of work,所有矿工都试图解决这个数学问题。一旦有一桩成功的交易,它将切换到权益证明,然后设置验证器来标记这个新的区块。

    Proof of Burn(焚烧证明)

    这种证明算法不会在昂贵的计算机设备上烧钱,而是把币送到一个不能复原的地址上。一旦你把币丢去这里,那就永远赎不回来了。你可以通过随机选择过程获得永久权限,以便能够在系统上挖掘。随着时间的推移,你在系统中的权益会衰减,最后你会想要烧掉更多的币来增加中奖几率。


    点击有惊喜


    展开全文
  • 个人在学习肖臻老师区块链课程中的手写笔记,用goodnotes记录的。在听课过程中的记录,可作为参考。
  • CIO应该开始拥抱区块链,从而探索出战略性的商业变革方案,但也要注意避免过度炒作。 全球每年由超过4万亿的商品运输,其中80%的搬运是通过海洋运输完成的,产生了大量的文书工作。处理和管理这些货物的文件成本...

    CIO应该开始拥抱区块链,从而探索出战略性的商业变革方案,但也要注意避免过度炒作。

    全球每年由超过4万亿的商品运输,其中80%的搬运是通过海洋运输完成的,产生了大量的文书工作。处理和管理这些货物的文件成本大于占到实际运输成本的五分之一。

    去年,一家物流公司和一家科技公司合作,运用区块链技术开发了一个国际联合分布式贸易平台。它提供了一个共享的、不可篡改的交易记录,并允许不同的合作伙伴任何时候访问这些信息。区块链技术存在分布式、不可篡改、加密等特性,但是区块链可以实现的业务场景远不止于此。

    寻找颠覆性商业机会的大型企业不仅仅是想获取效率的提升。基于此,他们需要真正的区块链解决方案。

    区块链为何引起CIOs的关注

    Gartner预测,到2030年,区块链将生成3.1万亿美元的新商业价值,但这项技术被主流应用要到2023年,组织机构应该从现在开始探索区块链技术。这种情况将变得尤为突出,大型跨国公司和数字巨头为了获取更大的市场份额,会实施区块链技术,比如分布式账本技术,从而强化其行业中心地位的业务模式。

    CIO因此需要在巨大的压力下,帮助指引企业应用区块链技术。那些已经运用区块链技术的企业将会处在一个更好的位置和更强的竞争力。

    “开发区块链技术要求企业去拥抱分布式技术与数字身份到他们的业务模型中。”

    对于CIOs而言,很有必要去理解区块链是什么,它如何工作,更重要的是,这项技术如何重塑业务的优先级,甚至是完全中断一些业务。但是只有3%的CIOs在他们的业务中成功应用区块链技术,这些应用的领域往往都是注重已有业务效率的提升,而不是业务的中断或者新价值的创造。

    “区块链技术提供了一系列的新经济、新商业和社会模式。”大卫弗龙,Gartner副总裁分析师说,“开发区块链技术要求企业拥抱分布式技术和参与数字身份战略运用到他们的业务模型和流程中,但这种策略不是直截了当的”。

    区块链引入了从如何同时竞争和协作的战略问题(例如,在行业联盟中)到缺乏技术互操作性、安全问题以及多种数据管理和监管情况的挑战,包括解决各种安全和隐私法,比如欧盟全球数据保护条例(GDPR)。

    什么是区块链的价值

    区块链允许互不认识的双方安全、直接地做生意,理论上不需要律师、银行、经纪人或政府参与其中。

    区块链确认参与者的身份信息,验证交易,确保每个人都按照规则进行。可以进行的交易与可以参与的人员都非常广泛,还包括机器,从而创造了巨大的商业可能。

    比如,一旦该技术完全成熟,并和人工智能、IOT等互补性技术结合,就可以自动代理驾驶人员,使用传感器记录的数据,与众多的汽车保险公司对保险费率进行谈判。

     

    什么是区块链

    区块链包含五大要素:分布式、加密性、不可篡改、匿名性以及去中心化。

    分布式:区块链参与者在物理上分布在不同的位置,通过网络联系在一起。每个参与者操作一个全量节点,维持一个全量的账本,当新的交易发生的时候,就会发生更新。

    加密性:区块链使用公钥和私钥等技术以半匿名的方式安全地记录数据块中的数据(参与者使用假名)。参与者可以管理他们的身份和其他个人信息,并且分享交易中需要的信息。

    不可篡改性:完整的区块链是签名加密的,时间戳,并按照顺序加入到账本中。记录不能被破坏或更改,除非参与者同意这样做。

    数字身份(匿名性):区块链上的交易和其他互操作涉及到价值交换的安全。价值是以令牌的形式出现,但可以代表任何东西,包括财务资产到数据到物理资产。令牌也允许参与者管理他们的个人数据,区块链业务的基本驱动力。

    去中心化:网络信息和网络运行的规则都是由分布式网络上的节点通过一种共识机制来维护的。实际情况中,分布式意味着没有单个的实体控制所有的机器、信息或者规则定义。

    理解了每一个元素,以及他们是如何组合成一起形成一个真实的区块链,给CIOs一个框架去解释区块链如何去做,以及澄清谬论。CIOs也可以使用这些元素去解释局部区块链解决方案与完整、增强型区块链解决方案之间的区别。

     

    Gartner区块链演进路线

    随着围绕区块链的炒作,供应商们纷纷向市场提供承诺和解决方案,这些承诺和解决方案大多关注于效率的提高。首席信息官必须理解实际解决方案和部分解决方案之间的区别,并投资于那些能带来真正好处的解决方案。

    大多数早期的区块链解决方案缺乏数字身份和分布式的功能。Gartner将这些解决方案称为“受区块链启发”的区块链方案,分为三个阶段。

     

    阶段1:区块链局部解决方案

    这个阶段开始于2012年,将持续到本世纪20年代早期。这些解决方案仅包含3大要素:分布式、加密性和不可篡改。通常,这些产品都是实验性的,没有完全实现,它们专注于通过简化现有流程来创造更高的效率。

    阶段2:区块链完整解决方案

    这个阶段的解决方案包括所有5个元素,目的是实现区块链的全部价值主张。目前,只有初创公司专注于这一成熟水平,尽管Gartner预计这些解决方案将在2023年左右在市场上获得动力。

    阶段3:增强型区块链解决方案

    第三阶段的区块链将连接互补性技术形成区块链完整的解决方案,这些互补性技术包括:AI,IOT和分散的自我权限认证技术(SSI)。

    “企业很容易犯错误,这将使他们失去充分利用区块链的时机,从而陷入对进步和能力的错误认识”,Gartner VP 分析员 查理斯多夫说,“将战略投资转向完整的区块链解决方案,而不是基于区块链的局部解决方案,后者会加强集中化流程,阻碍企业从区块链获得最大的商业价值”。

    区块链跨越行业边界

    CIOs可以开始研究区块链如何跨越行业边界。对于供应链而言,最初的应用范围从追踪芒果从农场到存储的能力(可追溯性),或证明真品从工厂到存储的传承(仿制品),到管理记录(效率)。

    政府也一直在探索潜在的应用程序,尽管许多还处于初期阶段,但已经出现了一些有趣的用例。例如,美国犹他州的一个县就在区块链进行市政选举。区块链解决方案也提高了问责制和衡量政策实际影响的能力。

    在金融服务行业,区块链为跨境支付、贸易融资、证券结算效率和更安全的身份识别系统提供了机会。但真正的转变将随着新的数字资产的创造和金融的分散化而发生。

    安全、技术和法律限制

    就像所有技术一样,区块链也面临诸多挑战。例如,现行法律可能仍需要修订或容纳区块链的使用场景,财务报告和合规性依然是不清晰的。该技术还缺乏法律、税收和会计框架、本地互操作性和可伸缩性,并且目前存在有限或不充分的治理模型和标准。

    许多版本的区块链就是在现行的操作模型下被创建的,其最初的目的是运用开源和分布式的协议,分散和终结中心化的实体、操作,流和业务模型。

    更进一步的是,区块链安全是面临的一项巨大挑战,其缺乏良好的实践与技术标准,尤其是联盟链的环境中。在加密货币中,例如,由于误解、基本代码错误、欺诈和安全错误,数以千万计的美元搁浅或被盗。围绕区块链账本的技术也存在安全漏洞,这意味着所有区块链项目都必须对技术、监管和合规性、人为误解和风险价值进行评估。

     

    区块链作为颠覆者

    比特币的推出时机似乎是有意设计的,为的是瓦解金融和银行业。然而,由于客户的心态、已建立和有效的解决方案以及技术的限制,它似乎不太可能按照最初的计划取得成功。在区块链可能具有破坏性的其他行业,厌恶风险的公司紧紧控制着风险因素,导致了渐进式的改进,而不是颠覆游戏规则的颠覆。缺乏管理者的理解也是一个重要的阻碍因素。

    这些行业包括医疗保健、供应链和政府。区块链的最终成功实施,甚至连优步(Uber)和Airbnb等传统颠覆者也可能会被颠覆。这些公司属于“点对点”(peer-to-peer)经济,它们对充当中间人的数字平台产生了依赖。

    希望利用区块链技术的公司将能够完全去除中央角色人物。由于上述技术挑战和常规的采用,在该领域实现变革需要时间,但完整区块链和增强区块链解决方案的潜力已经促使区块链原生公司(诞生于区块链之上的公司)创造出新的、有影响力的商业模式。

     

    展开全文
  • 搭建自己的区块链,人人能写区块链

    千次阅读 多人点赞 2019-06-22 09:52:03
    人人能写区块链?能做到吗? 一个自己的区块链,不是让程序员凭空想象,而是使用已经的开源平台,通过学习理念、工具、通过编写简答的函数即可以实现自己的区块链。 人人能写区块链吗? 目前比较著名的项目...

    如何实现自己的区块链? 人人能写区块链?能做到吗?
    写一个自己的区块链,不是让程序员凭空想象,而是使用已经的开源平台,通过学习理念、工具、通过编写简答的函数即可以实现自己的区块链。
    人人能写区块链吗?
    目前比较著名的项目Ethereum,你可以在Ethereum这个平台上实现自己的区块链。 关于Ethereum项目,所有的资料、文档、代码、开发技巧都是开放的,参考网站: https://github.com/ethereum,只要你懂一门编程语言,就可以实践自己的区块链,只要具备C++,go,JavaScript,Python 任何一门语言即可,因为编程语言的原理是相通的。
    区块链是什么?
    区块链英文名Blockchain,本质是保存持续增长的记录的分布式数据库。最奇妙的是区块链把分布式数据在技术上只保留了Insert、Query两个操作。
    如何才能实现这样一个系统呢?那么我们需要回答几个核心问题。
    如何保存数据?保存数据的困难有哪些?
    数据逐渐增加,如何应对?
    如何对之前的数据进行修改?
    解决方案 :
    如同数据结构的链表+结构体组合,不断的记录新的数据,然后将这些数据连接起来
    一个区块如何描述,其实就是LinkedList
    ClassDataBlock{ getData(); setData(); getPre(); getNext();}
    数据能否被修改呢?因为如果支持修改,可能引发很多的同步问题。那么能否不支持修改呢?实际上,GFS的整体架构就是构建在不可修改的数据结构之上。
    于是,我们推论出构建不可修改的串联的数据块。但是我们要注意的是虽然底层数据不能修改,但是上层的数据视图是可以修改的。
    如何让很多人都对数据有信心,相信是真实的,不能被篡改呢?每个人都保存一份同样的数据。
    如何添加数据呢
    我们添加的每一份数据都需要按照同样的方式添加到每个人保存的副本中。
    我们能否具有计算能力呢?为什么需要计算能力?
    我们从此可以得到一个通用的计算机,也把数据的修改模型更加地简化和通用化。
    我们如何定义计算能力呢?
    要回答这个问题,我们首先要想的是这个分布式的计算机的各个部分是如何构成的。
    谁来构成整个存储空间?每一个具体的地址。每一个地址保存了什么?数据。如何才能对地址计算呢?我们可以把对数据的处理逻辑也放入这个地址。那么一个地址到底需要什么呢?地址信息、财富信息、数据信息、代码。
    于是,所谓的状态就是指系统中每一个地址和地址对应的状态的集合。我们通过一个一个的交易来进入新的状态。
    接着, 我们可以把状态转移的过程也记录下来,这个就是记录transaction的block。这些block连接在一起,形成blockchain。
    如何应对同时写入的混乱
    如何防止很多人一起写造成的混乱呢?大家同时解决一个难题,谁先解出来,谁就能够写入。
    如何防止有人同时解出来?这个有可能,但是连续多次都是同时有人解出来的概率较低,于是选择链最长的那一个。
    具备以上基本概念,让我们在这里通过实际的代码进一步实战,实现一个支持Token的BlockChain。参考:Naivecoin: a tutorial for building a cryptocurrency
    官方网站:https://lhartikk.github.io( 具备基本的编程基础)
    如何保存数据
    区块链的基本概念是:保存持续增长的有序数据的分布式数据库。要实现自己的区块链,需要满足以下功能:
    定义数据块
    定义数据块之间的关系
    添加数据块的功能
    节点之间的通讯
    节点之间同步数据
    对节点的控制能力
    区块的结构
    因为区块链中的数据是相互连接的数据块,因此我们需要创建LinkedList来实现这样的场景。
    如上图所示,我们可以看到以下核心元素:
    index:区块的递增编号
    data:该区块所保存的数据
    timestamp:时间戳
    hash:通过SHA256算法对该区块进行的签名
    previousHash:前一个数据块的hash值,从而将区块串联了起来
    我们可以得到对应的代码:
    classBlock{
    publicindex:number;
    publichash:string;
    publicpreviousHash:string;
    publictimestamp:number;
    publicdata:string;
    constructor(index:number,hash:string,previousHash:string,timestamp:number,data:string) {
    this.index=index;
    this.previousHash=previousHash;
    this.timestamp=timestamp;
    this.data=data;
    this.hash=hash; }
    如何保证数据不被篡改
    在计算机的世界中,一切都是用数学来解释,用数学来证明。对于一个数据块,我们计算出它的摘要。只要保证数据有变化,必然会引发摘要变化即可。在这里我们使用的是SHA256的Hash算法。从这个角度来说,Hash也可以被看成这块数据的DNA。
    具体的Hash的过程如下,
    constcalculateHash=(index:number,previousHash:string,timestamp:number,data:string):string=>CryptoJS.SHA256(index+previousHash+timestamp+data).toString();
    聪明的读者可能会发现,这个简单的方法并不能防范更加复杂的黑客攻击。因此,我们会不断的改进我们的代码,以抵挡这个世界的某些恶意。
    但是现在的我们至少能够通过Hash来唯一的验证一个区块链的结构了。
    为什么?
    因为我们在做Hash的时候,也把这个区块对应的上一个区块的Hash放了进来,因此如果有人想要篡改整个区块链上的任何一个区块,都会产生蝴蝶效应,后续的区块都会为止失效。
    如上图所示,如果我们把区块44的数据从TREE改为STREET,那么它自身的Hash结果会改变,接着区块45中的previousHash也会发生改变,于是区块45的Hash也会改变,以此类推。因此,越早的区块发生异常,那么带来的影响就会越大。
    如何创建第一个区块
    第一个数据块的难点在哪里?它没有previousHash!因此,我们直接硬编码即可。
    constgenesisBlock:Block=newBlock(
    ,‘816534932c2b7154836da6afc367695e6337db8a921823784c14378abed4f7d7’,
    null,1465154705,‘my genesis block!!’);如何创建新的区块
    创建区块如同炒菜,需要备好所有的原料。如同以下的代码所示,我们需要找到最后一个有效的区块,推理出下一个区块的index,得到当前的时间戳,再结合上一个区块的hash和当前的数据,也就能知道当前区块的hash,从而创建出新的区块。
    constgenerateNextBlock=(blockData:string)=>{
    constpreviousBlock:Block=getLatestBlock();
    constnextIndex:number=previousBlock.index+1;
    constnextTimestamp:number=newDate().getTime()/1000;
    constnextHash:string=calculateHash(nextIndex,previousBlock.hash,
    nextTimestamp,blockData);
    constnewBlock:Block=newBlock(nextIndex,nextHash,
    previousBlock.hash,nextTimestamp,blockData);
    returnnewBlock;};
    区块保存在哪里
    在当前的版本中,我们只是保存在JavaScript所使用的内存中,因此很容易丢失,但是我们可以逐渐完善,让数据的保存越来越持久。
    constblockchain:Block[]=[genesisBlock];如何验证数据的有效性
    在任何一个时刻,如果其他人给了我们一个新的区块,我们如何验证这个区块是正确的呢?这需要符合以下的基本要求:
    区块之间的索引是+1递增的
    当前区块的previousHash需要和之前区块的Hash相同
    区块自身的Hash需要正确
    于是,我们实现的代码如下:
    constisValidNewBlock=(newBlock:Block,previousBlock:Block)=>{
    if(previousBlock.index+1!newBlock.index) {
    console.log(‘invalid index’);
    returnfalse; }elseif(previousBlock.hash!newBlock.previousHash) {
    console.log(‘invalid previoushash’);
    returnfalse; }elseif(calculateHashForBlock(newBlock)!newBlock.hash) {
    console.log(typeof(newBlock.hash)+’’+typeofcalculateHashForBlock(newBlock));console.log(‘invalid hash:’+calculateHashForBlock(newBlock)+’’+newBlock.hash);returnfalse; }returntrue;};
    这里还有一个细节,如果区块内数据的结构不正确,也可能是一个问题。因此我们还要额外进行判断。
    constisValidBlockStructure=(block:Block):boolean=>{
    returntypeofblock.index
    =‘number’&&typeofblock.hash
    =‘string’&&typeofblock.previousHash
    =‘string’&&typeofblock.timestamp===‘number’&&typeofblock.data===‘string’;};
    我们现在可以完整的验证一条区块链了吗?可以。我们首先要单独处理第一个区块,然后依次验证之后的每一个区块。
    constisValidChain=(blockchainToValidate:Block[]):boolean=>{
    constisValidGenesis=(block:Block):boolean=>{
    returnJSON.stringify(block)=JSON.stringify(genesisBlock); };if(!isValidGenesis(blockchainToValidate[])) {
    returnfalse; }for(leti=1;i
    if(!isValidNewBlock(blockchainToValidate[i],
    blockchainToValidate[i-1])) {
    returnfalse; } }returntrue;};
    区块链分叉了怎么办
    在一个分布式的环境中,有可能不同的人在同一个区块后添加了新的不同的区块,那我们要听谁的呢?听大多数人的话(尽管现实中大多数人的话也许……)!那谁才能代表大多数的人民呢?实力更强大,更长的那一条链。
    因此在遇到多条链的时候,我们可以直接选择更长的一条。具体代码如下,
    constreplaceChain=(newBlocks:Block[])=>{
    if(isValidChain(newBlocks)&&newBlocks.length>getBlockchain().length) {
    console.log(‘Received blockchain is valid.
    Replacing current blockchain with received blockchain’);
    blockchain=newBlocks;
    broadcastLatest(); }else{
    console.log(‘Received blockchain invalid’); }};节点之间要如何通讯
    因为在整个网络中有很多节点,大家都有可能去创建区块,这就需要大家通过协商通讯的方式达成共识,这需要以下三个基本能力:
    当个节点创建了一个区块,需要通知整个网络
    当一个节点连接上了一个新的节点,需要主动询问对方最新的区块
    当一个节点遇到一个新的区块,它会根据判断的结果向网络请求更多的区块
    上图给出了节点通讯的具体流程。需要注意的是,在我们的代码中,所有的连接都被爆存在了。我们并没有实现节点发现的功能,因此节点的位置需要手动的添加。
    如何控制节点
    我们需要一个对外的接口来控制一个节点,从而能够查看节点的区块、添加区块、查看连通的节点、添加节点。于是我们通过以下代码实现了HTTP对外的服务接口。
    constinitHttpServer=(myHttpPort:number)=>{
    constapp=express();app.use(bodyParser.json());
    app.get(’/blocks’, (req,res)=>{
    res.send(getBlockchain()); });app.post(’/mineBlock’, (req,res)=>{
    constnewBlock:Block=generateNextBlock(req.body.data);
    res.send(newBlock); });app.get(’/peers’, (req,res)=>{
    res.send(getSockets().map((s:any)=>
    s._socket.remoteAddress+’:’+s._socket.remotePort)); });app.post(’/addPeer’, (req,res)=>{
    connectToPeers(req.body.peer);res.send(); });app.listen(myHttpPort, ()=>{
    console.log(‘Listening http on port:’+myHttpPort); });};
    于是,我们可以直接访问接口进行控制。例如,获得全部区块的列表。
    系统的架构是什么
    如上图所示,我们每个节点都会向外提供两个服务:
    让外部用户能够控制这个节点的HTTP server服务
    支持节点之间通讯的Websocket HTTP server服务
    小结:如何保存数据
    综上所述,我们已经构建了能够保存区块的区块链的服务结构,实现了创建区块和控制节点的基本能力。让我们继续添加更多的功能吧。
    如何应对攻击
    在我们已经实现的版本中,每个人都能在其中添加区块,这样不仅可能造成混乱,而且如果有人拼命的添加区块也会阻塞整个网络。
    如何应对呢?
    那我们就限制每个人添加区块的能力吧。如何限制呢?记得你在网站每次注册新账号的时候都会出现的验证码吗?我们只要让大家在每次添加区块的时候都要做一道“难题”即可。这就是Proof-of-Work的基本原理,而这个解题过程就被称之为挖矿。
    因此,这个难题的设置会影响到节点添加区块的难度。越难的题会让我们越难添加区块,相对来说安全性会上升,但是延迟很可能增加。
    如何设置不同难度的题目
    一个好的题目要让计算机便于理解,运算规则相对简单,运算方式相对公平。于是结合Hash算法的题目被设计了出来:找到一个特定区块,这个区块的Hash需要有特殊的前缀。
    这个前缀越特殊,难度就越大。于是我们可以定义出题目的难度difficulty为你所定义的特殊的前缀是由几个0组成。例如,如果你只要求找到的区块的Hash有一个0(difficulty=0),那么可能相对简单;但是如果你要求你找到的区块的Hash的前缀有10个0(difficulty=10),那么就有点难了。下图给出了更细节的展示。
    我们可以相应的实现检查Hash是否满足difficulty的代码。
    consthashMatchesDifficulty=(hash:string,difficulty:number):boolean=>{
    consthashInBinary:string=hexToBinary(hash);
    constrequiredPrefix:string=’’.repeat(difficulty);
    returnhashInBinary.startsWith(requiredPrefix);};
    为了找到满足difficulty条件的Hash,我们需要对同一个区块计算出不同的Hash。但是这个Hash算法的一致性相矛盾。可是我们可以通过在区块中加入新的参数来实现Hash结果的变化,因为SHA256会因为数据的任何微小变化为完全变化。于是我们添加了一个叫做Nonce的参数,并且不断的改变这个参数直到挖到我们想要的Hash结果。于是一个区块的数据结构更新如下:
    classBlock{
    publicindex:number;
    publichash:string;
    publicpreviousHash:string;
    publictimestamp:number;
    publicdata:string;
    publicdifficulty:number;
    publicnonce:number;
    constructor(index:number,hash:string,previousHash:string,
    timestamp:number,data:string,difficulty:number,nonce:number) {
    this.index=index;
    this.previousHash=previousHash;
    this.timestamp=timestamp;
    this.data=data;
    this.hash=hash;
    this.difficulty=difficulty;
    this.nonce=nonce; }}
    如何解一个难题
    基于以上的分析,我们不断的增加Nonce的值,直到找到一个有效的Hash,具体代码如下:
    constfindBlock=(index:number,previousHash:string,timestamp:number,
    data:string,difficulty:number):Block=>{
    letnonce=;while(true) {
    consthash:string=
    calculateHash(index,previousHash,timestamp,data,difficulty,nonce);
    if(hashMatchesDifficulty(hash,difficulty)) {
    returnnewBlock(index,hash,previousHash,timestamp,
    data,difficulty,nonce); }nonce++; }};
    当我们找到了一个有效的Hash,就把这个区块广播给整个网络。
    如何确定难度
    虽然我们能够指定问题的难度,但是我们要如何设置难度呢?而且如何才能让网络的节点都认同这个难度呢?
    让我们回归到区块链的本身。区块链无非是一个区块的链表,并且每隔一段时间会加入一个新的区块。而我们的题目就是在控制加入区块的难度,也就是加入的时间间隔,于是我们引入一个全局参数:
    :定义了多久产生一个区块(Bitcoin是10分钟,Ethereum大概10-20秒)
    但是随着环境的变化,例如有更多的节点加入网络,我们并不能一致维持这个时间,因此我们每隔一段时间需要调整一下难度,于是我们引入第二个全局参数:
    :定义了每隔多久调整一次难度(Bitcoin是2016个区块,Ethereum是更加动态的调整)
    在我们的代码中,我们会设置间隔为10秒。
    //in seconds
    constBLOCK_GENERATION_INTERVAL:number=10;
    //in blocks
    constDIFFICULTY_ADJUSTMENT_INTERVAL:number=10;
    于是在我们的区块链中每产生10个区块就会查看区块的生成频率是否满足我们的预期
    。我们会根据预期和现实之间的差异决定如何调整难度。具体来说,我们判断差异是否到了2倍的范围,我们会对difficulty进行或者的操作。具体代码如下:
    constgetDifficulty=(aBlockchain:Block[]):number=>{
    constlatestBlock:Block=aBlockchain[blockchain.length-1];
    if(latestBlock.index%DIFFICULTY_ADJUSTMENT_INTERVAL
    =&&latestBlock.index!) {returngetAdjustedDifficulty(latestBlock,aBlockchain); }else{returnlatestBlock.difficulty; }};constgetAdjustedDifficulty=(latestBlock:Block,aBlockchain:Block[])=>{
    constprevAdjustmentBlock:Block=
    aBlockchain[blockchain.length-DIFFICULTY_ADJUSTMENT_INTERVAL];
    consttimeExpected:number=BLOCK_GENERATION_INTERVALDIFFICULTY_ADJUSTMENT_INTERVAL;
    consttimeTaken:number=latestBlock.timestamp-prevAdjustmentBlock.timestamp;if(timeTakentimeExpected
    2) {
    returnprevAdjustmentBlock.difficulty-1; }else{returnprevAdjustmentBlock.difficulty; }};时间戳被篡改了怎么办
    我们题目的难度的调整需要用到区块中保存的时间戳,但是这个时间戳可以由一个节点写入任何值,我们如何应对这样的攻击呢?这里的难点还在于不同节点上的时间本来就会有一定的差异。但是我们知道如果区块的时间戳和我们自己的时间相差越远则越可能有问题,因此我们把这个差异限制上一个区块的创建时间到当前时间范围的1分钟以内。
    constisValidTimestamp=(newBlock:Block,previousBlock:Block):boolean=>{
    return(previousBlock.timestamp-60有人通过低难度产生超长链怎么办?
    我们在上一节讨论过当遇到分叉的时候,选择更长的一个。但是一个恶意节点可以产生一个很长的但是每个区块的难度都是最简单的分叉。这样怎么办?那就把选择标准从最长调整为最难的。也就是说,我们会选择累计解题难度最大的分叉,因为这背后所代表的人民的力量更加强大。
    如何计算累计的难度呢?因为每加一个0,我们的计算难度的期望会乘以2,所以我们计算每个区块的来求得累计的难度,以此做为选择标准。
    如上图所示,再A和B两个链条中,虽然B更短,但是因为B的难度更大,所以我们会选择B。
    有一个需要注意的是,这里的关键是难度,而并非Hash的前置的0,因为我们有可能碰巧得到一个更多的0的情况。这个思路被称之为“中本聪共识”,是中本聪发明Bitcoin时的一个重要贡献。因为每个节点只有相对较小的Hash计算能力,因此他们会倾向于选择累计难度更长的链条来贡献自己的力量,从而让自己的贡献得到认可。
    小结:如何应对攻击
    Proof-of-work的特点在于难于计算,易于验证。因此寻找特定前缀的SHA256成为一个很好的难题。
    我们已经在代码中加入了难度,并且节点可以通过挖矿来把区块添加到区块链中。
    如何交易
    我们在前两节实现的区块链只是对数据的基本保存,如何能够在这个基础上构建金融体系?但是一个金融体系的基本需求是什么呢?
    所有权:一个人能够安全的拥有token
    交易权:一个人能够把自己的token和他人交易
    但是我们的区块链是一个没有“信任”的分布式的网络,如何才能构建出“确定性”呢?这需要我们找到一个不可抵赖的证明体系。
    如何证明你是你
    其实证明自己往往是最难的,这需要我们落地到一个我们可以相信的事情。想一想古代碎玉为半,之后团圆相认的场景。在计算机的世界也是一样,我们把一块美玉的一半告诉全世界,然后把另一半藏在自己身上,这样之后你自己能够拼接处这块美玉。
    但这背后的难点在于,别人有了你公布出来的一半的玉,是可以伪造另一半的。但是在计算机的世界里,公钥加密体系却没有这个缺陷。
    你有两个钥匙:公钥和私钥。公钥是由私钥推演出来的,并且会公布给所有人。对于你自己发出去的信息,你都可以用你的私钥签名。其他人会收到你的信息和你的签名,然后他会用你的公钥来验证这个信息是否是通过你的私钥进行的签名。具体流程如下图所示。
    具体来说,我们会选择椭圆曲线加密算法(ECDSA)。到目前为止,我们引入了密码学中的两个核心工具:
    SHA256来支撑区块数据一致性验证
    ECDSA来支撑用户账号的验证
    公钥和私钥长什么样
    一个有效的私钥是一个32字节的字符串,示例如下:
    一个有效的公钥是由‘04’开头,紧接着64个字节的自负换,示例如下:
    公钥是由私钥演绎得到的,我们可以直接把它做为区块链中一个用户的账号地址。
    如何记录一次交易
    我们已经能够让用户证明自己是谁了,现在就要记录他们之间的交易了。我们需要三个信息
    从哪里来:发送者地址
    到哪里去:接收者地址
    交易多少:数量
    即便如此,我们依然有个疑问?发送者如何证明自己有这个token呢?那么他就需要提供之前他获得这个token的证据。于是我们还需要第四个信息:指向自己的证据的指针。一个例子如下图所示。
    于是我们需要两个结构分别表示交易的发起者和交易的接收者。
    接收者长什么样
    对于接受者,我们需要知道他的地址和交易的数量。如上一节所述,地址是ECDSA 的公钥。这意味着,我们还需要保证只有对应私钥的拥有者才能进一步操作这些token。这个结构体的代码如下:
    classTxOut{
    publicaddress:string;
    publicamount:number;
    constructor(address:string,amount:number) {
    this.address=address;
    this.amount=amount; }}发起者长什么样
    交易的发起者需要提供自己token来源的证据,也就是指向之前的交易。但是他要证明自己对这个交易的拥有权,因此需要提供通过自己私钥加密的签名。这个结构体的代码如下:
    classTxIn{
    publictxOutId:string;
    publictxOutIndex:number;
    publicsignature:string;}
    需要注意的是这里保存的只是通过私钥进行的签名,而不是私钥本身。在区块链的整个系统中,仅仅存在他的公钥和签名,而不会出现他的私钥。
    如上图所示,整个过程就是发起者解锁了txIns中的tokens,然后把它们转给了TxOut中的接收者。
    完整的交易长什么样
    结合之前的讨论,我们可以构建出最终的交易:
    classTransaction{
    publicid:string;
    publictxIns:TxIn[];
    publictxOuts:TxOut[];}
    如何唯一表示一次交易
    我们依然可以使用SHA256来进行Hash,并且使用这个Hash来做为交易的id。这里要注意的是我们并没有包含发起者的签名,这个会在之后添加。
    constgetTransactionId=(transaction:Transaction):string=>{
    consttxInContent:string=transaction.txIns.map((txIn:TxIn)=>txIn.txOutId+txIn.txOutIndex) .reduce((a,b)=>a+b,’’);
    consttxOutContent:string=transaction.txOuts.map((txOut:TxOut)=>txOut.address+txOut.amount) .reduce((a,b)=>a+b,’’);
    returnCryptoJS.SHA256(txInContent+txOutContent).toString();};如何对交易进行签名
    因为在区块链中所有的交易都是公开的,因此要保证没有人能够利用这些交易进行攻击。于是我们需要对所有敏感的信息都进行签名。具体代码如下:
    constsignTxIn=(transaction:Transaction,txInIndex:number,
    privateKey:string,aUnspentTxOuts:UnspentTxOut[]):string=>{
    consttxIn:TxIn=transaction.txIns[txInIndex];
    constdataToSign=transaction.id;
    constreferencedUnspentTxOut:UnspentTxOut=
    findUnspentTxOut(txIn.txOutId,txIn.txOutIndex,aUnspentTxOuts);
    constreferencedAddress=referencedUnspentTxOut.address;
    constkey=ec.keyFromPrivate(privateKey,‘hex’);
    constsignature:string=toHexString(key.sign(dataToSign).toDER());
    returnsignature;};
    但是我们会发现这里只是对交易id进行了签名,这样足够了吗?
    一种潜在的攻击方式如下:当攻击者CCC收到一个交易:从地址AAA向地址BBB发送10个token,交易id为0x555…。他会尝试把接受者修改为自己,然后把这个交易发送到网络中。于是这个消息变成了:从地址AAA向地址CCC发送10个token。但是,当另一个节点DDD接收到这个交易信息之后,会进行验证,他首先计算交易id。但是这时候因为接受者被改变了,因此交易id也会改变,例如成为了0x567…。于是发现问题。
    及时攻击者也修改了id为0x567…,但是AAA只是对0x555…进行了签名,因此签名的数据会不匹配。因此,攻击者也会被识破。
    到目前为止,整个协议看似是安全的。
    如何找到用户拥有的token
    在一起交易中,发起者需要提供自己所拥有的没有使用的token。因此,我们需要从当前的区块链中找到这些信息,于是我们需要维持整个系统中没有花费掉token的情况。这样的数据结构如以下代码所示:
    classUnspentTxOut{
    publicreadonlytxOutId:string;
    publicreadonlytxOutIndex:number;
    publicreadonlyaddress:string;
    publicreadonlyamount:number;
    constructor(txOutId:string,txOutIndex:number,address:string,amount:number) {
    this.txOutId=txOutId;
    this.txOutIndex=txOutIndex;
    this.address=address;
    this.amount=amount; }}
    我们进一步可以把系统中所有未花费的token记录在一个数组中:
    letunspentTxOuts:UnspentTxOut[]=[];如何更新未花费的数据信息
    我们什么时候更新呢?当新的区块产生的时候。因为这个区块里会包含新的交易信息。因此,我们需要从新的区块中找到所有未花费的token的信息,并且记录在newUnspentTxOuts之中,代码如下:
    constnewUnspentTxOuts:UnspentTxOut[]=newTransactions.map((t)=>{returnt.txOuts.map((txOut,index)=>newUnspentTxOut(t.id,index,txOut.address,txOut.amount)); }) .reduce((a,b)=>a.concat(b), []);
    我们同时也要知道哪些未被花费的token被花费掉了,这个被记录在consumedTxOuts,代码如下:
    constconsumedTxOuts:UnspentTxOut[]=newTransactions.map((t)=>t.txIns) .reduce((a,b)=>a.concat(b), []) .map((txIn)=>newUnspentTxOut(txIn.txOutId,txIn.txOutIndex,’’,));
    最终我们通过删除已经花费的并且加上新的未话费的,从而产生了新的未话费�数组resultingUnspentTxOuts,具体代码如下:
    constresultingUnspentTxOuts=aUnspentTxOuts.filter(((uTxO)=>!findUnspentTxOut(uTxO.txOutId,uTxO.txOutIndex,consumedTxOuts))) .concat(newUnspentTxOuts);
    以上逻辑通过updateUnspentTxOuts的方法来实现。需要注意的是这个方法要在验证了区块正确性的基础上再来执行,否则会产生各种风险。
    如何验证交易的有效性
    刚才提到了,我们需要验证交易的有效性,要如何做呢?这背后要思考的是有什么情况会产生异常。
    交易结构异常怎么办?我们需要判断交易的结构如何符合我们的标准。
    constisValidTransactionStructure=(transaction:Transaction)=>{if(typeoftransaction.id!
    ‘string’) {console.log(‘transactionId missing’);returnfalse; }…//check also the other members of class}
    交易id异常怎么办?我们需要进行判断。
    if(getTransactionId(transaction)!transaction.id) {console.log(‘invalid tx id:’+transaction.id);returnfalse; }
    发起者信息异常怎么办?我们可以对签名进行判断,同时也要判断token尚未被花费。
    constvalidateTxIn=(txIn:TxIn,transaction:Transaction,aUnspentTxOuts:UnspentTxOut[]):boolean=>{constreferencedUTxOut:UnspentTxOut=aUnspentTxOuts.find((uTxO)=>uTxO.txOutId
    =txIn.txOutId&&uTxO.txOutId=txIn.txOutId);if(referencedUTxOutnull) {console.log(‘referenced txOut not found:’+JSON.stringify(txIn));returnfalse; }constaddress=referencedUTxOut.address;constkey=ec.keyFromPublic(address,‘hex’);returnkey.verify(transaction.id,txIn.signature);};
    交易数量异常怎么办?我们需要对发起者标注的未花费的数量和交易的实际数量进行对比,查看两者是否相等。
    consttotalTxInValues:number=transaction.txIns.map((txIn)=>getTxInAmount(txIn,aUnspentTxOuts)) .reduce((a,b)=>(a+b),);consttotalTxOutValues:number=transaction.txOuts.map((txOut)=>txOut.amount) .reduce((a,b)=>(a+b),);if(totalTxOutValues!totalTxInValues) {console.log('totalTxOutValues ! totalTxInValues in tx:’+transaction.id);returnfalse; }
    区块链的token最初从哪里来
    我们可以不断的回溯每一个交易,但是最初的交易的token从哪里来呢?这需要我们定义无中生有的基础交易。
    在基础交易中,它只有接收者,而没有发起者。这如同国家银行印刷了新的钞票。在我们的区块链中,将其定义为50。
    constCOINBASE_AMOUNT:number=50;
    这个没有起点的交易从哪里来呢?来自于我们对支撑系统的“矿工”的奖励。每当你挖出一个区块,系统会奖励你50个token。

    展开全文
  • 区块链

    万次阅读 多人点赞 2019-03-18 12:17:47
    简述区块链 区块链 区块链的本质是一个分布式的公共账本,任何人都可对这个账本进行核查,但不存在单一的用户可以对它控制。在区块链系统中的参与者共同维持账本的更新:它只能按照严格的规则和共识进行修改。 从...
  • 用java写区块链

    2019-11-23 15:12:48
    区块链就好比多个区块连接起来。其中每一块都将拥有自己的签名,签名由其前面的块签名、当前块的一些数据(例如交易信息)生成。  每个块不仅仅包含它之前的块信息,同时也包含自身。如果前面一块内容改变了,其...
  • 第一章:最小可行区块链 概览 区块数据结构 区块哈希 创世块 创建区块 保存区块链 验证区块完整性 选择最长链 节点间通信 操作节点 架构 运行测试 小结 概览 区块链的基础概念非常简单, 说白了就是一个维护着一个...
  • 《图说区块链的乱七八糟

    千次阅读 2017-12-18 13:02:18
    我购买的这本书,看了半本书了,感觉的的乱七八糟,狗屁不通,简直是随便各种抄写的各种乱叠加后悔买了这本书,浪费钱,浪费时间
  • Python从从零零开开始始创创建建区区块块链链 这篇文章主要...对数字货币的崛起感到新奇的我们并且想知道其背后的技术 区块链是怎样实现的 但是完全搞懂区块链并非易事我喜欢在实践中学习通过代码来学习技术会掌握得
  • 自己动手写区块链(Java版)2018年开始区块链真是火啊。一夜暴富的例子一直在传说。今天我们就自己动手一个基本的区块链。先简单的说一下区块链是个什么(相信你早就知道了)。区块链就是一个链表。把一堆区块串...
  • 区块链】 三十分钟一个比特币区块链--大学生入门区块链的启蒙课
  • 通过一个区块链原型程序学习区块链 网上看到一篇翻译文章:https://learnblockchain.cn/2017/10/27/build_blockchain_by_python/ 学习一门技术最好的方法就是自己做一个,水平有限,手敲了一遍这个代码,边敲...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 34,838
精华内容 13,935
关键字:

区块链怎么写