数据专栏

智能大数据搬运工,你想要的我们都有

科技资讯:

科技学院:

科技百科:

科技书籍:

网站大全:

软件大全:

【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
一、区块链简介
简单地说,区块链就是一种去中心化的分布式账本数据库。去中心化,即与传统中心化的方式不同,这里是没有中心,或者说人人都是中心;分布式账本数据库,意味着记载方式不只是将账本数据存储在每个节点,而且每个节点会同步共享复制整个账本的数据。同时,区块链还具有去中介化、信息透明等特点。
二、区块链的关键技术
1. 点对点分布式技术(P2P): 点对点技术(peer-to-peer, 简称P2P)又称对等互联网络技术,它依赖网络中参与者的计算能力和带宽,而不是把依赖都聚集在较少的几台服务器上。P2P 技术优势很明显。点对点网络分布特性通过在多节点上复制数据,也增加了防故障的可靠性,并且在纯P2P网络中,节点不需要依靠一个中心索引服务器来发现数据。在后一种情况下,系统也不会出现单点崩溃。
2. 非对称加密技术:非对称加密(公钥加密)指在加密和解密两个过程中使用不同密钥。在这种加密技术中,每位用户都拥有一对钥匙:公钥和私钥。在加密过程中使用公钥,在解密过程中使用私钥。公钥是可以向全网公开的,而私钥需要用户自己保存。这样就解决了对称加密中密钥需要分享所带来的安全隐患。非对称加密与对称加密相比,其安全性更好:对称加密的通信双方使用相同的秘钥,如果一方的秘钥遭泄露,那么整个通信就会被破解。而非对称加密使用一对秘钥,一个用来加密,一个用来解密,而且公钥是公开的,秘钥是自己保存的,不需要像对称加密那样在通信之前要先同步秘钥。
3. 哈希算法:哈希算法又叫散列算法,是将任意长度的二进制值映射为较短的固定长度的二进制值,这个小的二进制值称为哈希值。它的原理其实很简单,就是把一段交易信息转换成一个固定长度的字符串。
4. 共识机制:由于加密货币多数采用去中心化的区块链设计,节点是各处分散且平行的,所以必须设计一套制度,来维护系统的运作顺序与公平性,统一区块链的版本,并奖励提供资源维护区块链的使用者,以及惩罚恶意的危害者。这样的制度,必须依赖某种方式来证明,是由谁取得了一个区块链的打包权(或称记帐权),并且可以获取打包这一个区块的奖励;又或者是谁意图进行危害,就会获得一定的惩罚,这就是共识机制。通俗一点来讲,如果中国一名微博大V、美国一名虚拟币玩家、一名非洲留学生和一名欧洲旅行者互不相识,但他们都一致认为你是个好人,那么基本上就可以断定你这人还不坏。
三、区块链必备技能
区块链技术可以粗略的分为两方面,一个是做链上应用的,一个是做底层平台优化。
链上应用指的就是DAPP,需要与区块链底层做数据交互,需要运用智能合约做应用逻辑设计,其余跟web开发差不多,需要掌握基本的web开发技能,区块链的接口封装与数据传输技能,智能合约的设计技能。
底层优化人才是目前各大公司在竞相争取的人,要求明白区块链的底层设计架构原理是外汇常见问题http://www.kaifx.cn/lists/question/,包括P2P传输机制,共识算法实现机制,非对称加密的设计与运用等,目前区块链的实际落地瓶颈在于其交易性能的局限性,大家会发现现在市面上很多区块链公司打出的广告都在于如何如何优化了区块链性能这一块,而这方面则需要一些对底层架构比较熟悉的人才来完善,面向底层架构的人才,技能要求相对较高,密码学原理、P2P机制、docker等等,具备这些技能的人才目前在市场上是远远的供不应求。
别的区块链钱包设计、安全公司等,分别面向于接口封装调用设计,智能合约模拟攻击...还有一种我个人认为是区块链体系中最有价值的方向,是基于区块链token的经济模型的设计,这个不靠技术,得靠眼光和行业经验。
区块链
2019-12-04 16:56:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
没经过真实攻击一次次洗礼且保持进化的公链都不是安全的公链,51%攻击一旦成为真实场景下的成熟攻击手法,各个非大型公链及对接了一堆小公链币种的都需要小心了,风控机制需要特别增加一项:双花攻击是什么呢?万一出现双花攻击,怎么办?

让我们举个简单的例子,例如你在购物中心刷卡买东西。这种行为面临着三种危险:

首先,刷卡这种行为,校验的是你的信用卡信息,也就是说只要给刷卡机提供同样的信息,就能从你的账户里把钱刷走。没有错,很多朋友都听说过,有犯罪组织专门从事复制卡信息的勾当,之后“盗刷”你的卡。在一些不发达国家的小店里刷卡就特别容易中招。

其次,负责记账和结算的卡组织和银行的服务器可能被黑客攻破,造成数据泄露和伪造交易。回首近几年一波又一波某某大公司数据库被黑客攻入的新闻,这危险并非危言耸听。

最后,还有一种可能,就是用卡人自己可能利用系统网络延迟,在进行第一笔交易、用完所有额度后,趁系统还没记账把额度扣完,立刻进行第二笔交易,形成诈骗。当然目前的结算系统延迟极小,这情况不太可能,不过像在优惠券或者抢购资格这种另外搭建的相对脆弱的系统上还是有可能的。

网上支付也一样,犯罪分子可以用特殊手段(例如木马,伪造WIFI等)截获你跟服务器之间的传递数据,如果商家加密技术太弱的话信息就可能被破解——嗯,某国很多时候数据干脆是不加密的。所以大家才一直被警告不要乱装程序、不要连可疑的WiFi。

区块链是怎么正确处理这些问题的呢?让我们以比特币交易为例,逐条分析。

首先,比特币拥有者想要完成某项交易,例如买手机吧,他会向全网广播:我小A向小B支付1个比特币。
– 与这条信息一起的,还有一条加密信息,这条信息是用Hash函数对上一条信息加密生成一个摘要后,再用A的私钥进行加密的(称为私钥“签名”)。
– 接收到这条信息的B和其他用户先用同样的Hash函数对明文信息生成摘要,再用A的公钥对加密信息进行解密,如果解密得到的摘要与明文生成的摘要相同,便认为信息确实是A发出的,且没有经过篡改。
– A的公钥和Hash是公开的,私钥则无法算出,只有A知道,这样就既保证了交易的达成,又保证了A的信息无法被窃取。
其次,由在POW(运算力证明)中胜出的矿工负责这段时间的记账,事先完全无法知道究竟哪个矿工来记账,黑客也就无从黑起,除非碰运气。
最后,在传统系统中因为结算速度极快而不太可能的情况,在比特币网络中反而可能性比较大。如昨天所说,因为没有中心化的管理者,交易确认的时间要长很多,使得这种诈骗有可能实现,这就是比特币的double spending双重花费问题,简称“双花”。
双花攻击
双花攻击是同一笔UTXO在不同交易中的花费,双花不会产生新的货币,只能把自己花出去的钱重新拿回来。
这个攻击方法给了我灵感,实际上这道题就是使用双花攻击中的51% 股票代码查询www.gendan5.com/topic/lcSearch.html。attack。51% attack指的是攻击者如果可以拥有超过全网50%的算力,就可以创造一条高度大于原始链的链,攻击者可以发送一个新的块到这条链上。(如果有对比特币进行51%数字货币attack成功的案例,最大的危害在于人们对比特币的信心受损导致的比特币大跌而不是51% attack本身带来的危害)
如何进行51% attack攻击?在这道题中,就是创造一条超过原始链的长度。为了在后续讲解中方便,先写出题目给出的几个块,主链上块前有*
*块1(创世区块):银行发行100w币
*块2(1):黑客转走99w9999,银行留1 *块3(1):空块(什么都没操作)
具体操作就是从块1之后append一个块,把银行的100w转到shop中
*块1(创世区块):银行发行100w币
*块2(1):黑客转走99w9999,银行留1 *块3(1):空块(什么都没操作)
块2(2)--shop转走100w
(还可以随意转钱?就是有这种操作23333)
下一步,在自己append的块后append一个空块
*块1(创世区块):银行发行100w币
*块2(1):黑客转走99w9999,银行留1 *块3(1):空块(什么都不发生)
块2(2)--shop转走100w 块3(2)--空块(什么都不发生)
再来一次同样的操作
*块1(创世区块):银行发行100w币 块2(1):黑客转走99w9999,银行留1 *块2(2)--shop转走100w
块3(1):空块(什么都没操作)
*块3(2)--空块(什么都不发生) *块4(1)--空块(什么都不发生)
此时最长的链为块1-块2(2)-块3(1)-块4(1)。这样,我们就构造了一个比题目给我们还要长的链,区块链这套逻辑会把最长的链当做主链,主链从块2(2)处分叉,块2(1)失效了,shop账户中多了100w,我们获得一个钻石。接下来系统在购买钻石的块3(2)块后添加一个块,转走商店中的100w到商店钱包。
*块1(创世区块):银行发行100w币 块2(1):黑客转走99w9999,银行留1 *块2(2)--shop转走100w
*块3(2)--空块(什么都不发生)

*块4(1)--空块(什么都不发生)
*块5(1)--把100w转到shop_wallet_address
那么另一个钻石该怎么获得呢?继续利用50% attack攻击,从块4(1)分叉,添加空块
*块1(创世区块):银行发行100w币 块2(1):黑客转走99w9999,银行留1 *块2(2)--shop转走100w
*块3(2)--空块(什么都不发生)

*块4(1)--空块(什么都不发生)
*块5(1)--把100w转到shop_wallet_address
块5(2)--空块(什么都不发生)
再append一个空块
*块1(创世区块):银行发行100w币 块2(1):黑客转走99w9999,银行留1 *块2(2)--shop转走100w
*块3(2)--空块(什么都不发生)
*块4(1)--空块(什么都不发生)

块5(1)--把100w转到shop_wallet_address

*块5(2)--空块(什么都不发生)
*块6(1)--空块(什么都不发生)
主链变为块1-块2(2)-块3(1)-块4(1)-块5(2)-块6(1),块5(1)失效,shop拥有100w,钻石+1,得到flag。

五月,比特币黄金遭遇了51%攻击,此次攻击之后,系统超388200个BTG被双花;六月,ZEN也遭受到两次同类型攻击。‘双花’攻击就像一只蛰伏的野兽,平时不易感知,可它随时可能会威胁到你的安全。
对于51%攻击与‘双花’问题,很多用户一直都颇有微词。那么今天,我想先跟大家探讨一下这个‘双花’攻击。
‘双花’一词始现与比特币系统中,当时有朋友问了这样一问题,“在现实世界中,我买一瓶水花一块钱,钱立马就进了别人的口袋,但在比特币系统中,我发起转账到交易成功的这段时间,钱还是在我的账户里,这时候,我可不可以又付给另一个人呢。”
区块链
2019-12-04 16:38:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
大数据与区块链有什么关系?区块链无非创造了一种让人不依赖于信任前提条件的数据化确权,能够让大数据更精细化地流通,体现出价值。如果把数据比作数学经济时代的石油,那么区块链是石油的精炼厂,只有通过精炼的石油裂解成为汽油,柴油,煤油,沥青,才能在工业关节中产生价值。不然未被精细化确权的数据永远是通过数据大集中粗暴地流转,那仍然是在地表以下流动的一种液态化石而已。
所以我认为 数秦科技 所抓住的区块链加大数据赛道正是让数据能够工业化,让数字经济真正形成规模的方向。不然,没法被确权,没法授权,没法精细化流通,的未经过精炼的黑色原始数据石油,大概只能被用来作为“阙勒霍多”促进暴雷了。
区块链
2019-12-03 15:24:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
“把区块链作为核心技术自主创新重要突破口,加快推动区块链技术和产业创新发展。”作为目前最具发展前景的区块链技术,当它遇上6G又会产生怎样的化学反应?益链科技董事长朱浩冰先生就“区块链+6G”的未来发展表达了自己的看法。朱浩冰先生表示,十年之后,一个新的,巨大的,无处不在的价值互联网——“全球区块链”——形成。这会是一个怎样的“区块链+6G”世界?朱浩冰先生有如下17条预言:
1. 6G实现了以每一个个体为中心的新服务模式。
2. 6G的引入,将大幅提升数据的量级,从而让数据生产者可以获得更多的收益。5G将提供的链接是数以千亿级别来计算的,所有的链接结果都将生成数据,数据的使用产生价值;而数字法币的完善提供了最佳的激励载体;区块链天生就是一个非常简单、可靠的支付网络,在区块链的世界里,这种激励可以以最小的数据包为单位,进行实时的激励;数据的价值在最初就得到确认,并且回报直接给予数据生产者;这是一个高效、公平、透明的激励系统。6G的引入,将大幅提升数据的量级,从而让数据生产者可以获得更多的收益。
3. 6G对原来被3G/4G占用的频谱的重新使用,使得整个移动网络的效率更高。并且借助区块链这个基本能力,实现“分层次的”“多中心的”频谱使用共识和动态分配,即使是跨牌照协同也成为技术性的可能和商业性的必然;这得益于区块链的“incentive”的基本能力。公共服务的频谱资源进行充分的共享,最大限度的使用自然赐予人类的电磁波资源。
4. 6G技术再次分裂。天下之事大凡如此,分久必合合久必分;2G/3G/4G/5G从分裂走向了融合,但是包袱太重,兼容发展的6G技术和一种完全不兼容以上系统的6G备选技术同时出现。所谓的高技术门槛,总能换个思路找到解决方案,人为的门槛总是会变得无效。轻装上阵的新6G不是一个纯物理层技术,而是可以与区块链深度融合的Infrastructure, 以大道至简的美,成为主流选择之一。再一次的,区块链的“incentive”本能又起了作用。
5. 以区块链和6G为基础的Fog computing利率决议http://www.gendan5.com/decision/usd.html
的能力形成;益链科技2018年青皮书中提出的分布式存储,分布式计算,分布式人工智能组成的服务成为基础性服务,服务于人类生活和生产各个方面;从而在更大的程度上提升了人类的工作效率,给人类的生活带来更多的“自由”和“平等”的机会;将人类的智能与意识应用于更加具备创新性的活动中去;人类对艺术等非物质生活的要求更高,并获得超越物质的愉悦。互联网时代,人类的最大能力是获取知识并消化的能力;区块链时代,人类的最大能力将是充分利用工具,发挥个人创造力的时代。
6. 区块链为支持以上的技术发展,“有限共识”“有效共识”“边界共识”等技术将发展起来。
7. 即使根据摩尔定律的推测,计算存贮转发的等能力提高了150倍,但是数据与价值在不断地相互校验中发展,没有价值的数据逐步淘汰,有价值的数据持续沉淀;这种功利主义的好处是“有价值”数据在不断积累,而其坏处是暂时没有交换价值的数据被抛弃,
于是一种新的商业机会又出现了:“无价值数据”的再利用,就类似物质世界里的不良资产处理,也成为一门不错的生意;一个高技术门槛的生意。
8. 需要注意的是,6G网络中的50%以上是非传统电信运营商建设,关于这一点的理由有二:1)美国的利益和力量。大力推进自由频谱对美国利益最大,美国将在6G的芯片、器件、材料、知识产权等方面获得最大量的客户(远远超过现在的牌照频谱的设备制造者),还将借助于其Go Internet, Go Mobile, Go Chain这个持续的价值转移之路上持续占据云端发展的制高点而不断受益;2) 市场竞争的必然结果,更扁平的网络,更低的进入门槛,更多的玩家,全人类受益。
当我们每个人都在使用4G移动通讯技术的时候,5G被提了出来。而5G还未普及(目前也只是完成了第一阶段,距离正式商用还有很长一段时间),6G就已经被很多人畅想,而且某些企业已经开始了相关的探索与研究,中国工信部甚至明确表示中国已着手研究6G。

那么就会有人问,4G已经够好了、够用了,为什么还要弄个5G和6G呢?
很显然,在目前网络数据还不是海量的情况下,4G完全足以支撑。但之后物联网、无人驾驶、VR、3D一旦大规模普及,未来对于网络的需求,我们可能会面对1000倍的数据容量增长,10到100倍的无线设备连接,10到100倍的用户速率需求,也就是说未来的4G网络或许无法满足这些需求,所以5G、6G也就成为了必然产物。
在5G的加持下,我们可以在一秒钟内下载一部高清电影,但4G可能要10分钟。
而我们今天所说的6G,则是5G之后的延伸与扩展,预计2020年开始研发,2030年正式投入商用。6G则是主要针对物联网。
对于十年后的6G和区块链,朱浩冰先生表示,以终为始,当将眼光放长远,就可以跳出眼前的纷繁,看清楚未来的靶心。未来十年6G与区块链的发展,大家拭目以待!
区块链
2019-12-02 17:33:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>> pragma solidity >=0.4.22 <0.6.0; /** * @title SafeMath * @dev Math operations with safety checks that throw on error */ library SafeMath { /** * @dev Multiplies two numbers, throws on overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256 c) { if (a == 0) { return 0; } c = a * b; assert(c / a == b); return c; } /** * @dev Integer division of two numbers, truncating the quotient. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { // assert(b > 0); // Solidity automatically throws when dividing by 0 // uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return a / b; } /** * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend). */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { assert(b <= a); return a - b; } /** * @dev Adds two numbers, throws on overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256 c) { c = a + b; assert(c >= a); return c; } } /** * @title ERC20Basic * @dev Simpler version of ERC20 interface * @dev see https://github.com/ethereum/EIPs/issues/179 */ contract ERC20Basic { function totalSupply() public view returns (uint256); function balanceOf(address who) public view returns (uint256); function transfer(address to, uint256 value) public returns (bool); event Transfer(address indexed from, address indexed to, uint256 value); } /** * @title ERC20 interface * @dev see https://github.com/ethereum/EIPs/issues/20 */ contract ERC20 is ERC20Basic { function allowance(address owner, address spender) public view returns (uint256); function transferFrom(address from, address to, uint256 value) public returns (bool); function approve(address spender, uint256 value) public returns (bool); event Approval(address indexed owner, address indexed spender, uint256 value); } /** * @title Basic token * @dev Basic version of StandardToken, with no allowances. */ contract BasicToken is ERC20Basic { using SafeMath for uint256; mapping(address => uint256) balances; uint256 totalSupply_; /** * @dev total number of tokens in existence */ function totalSupply() public view returns (uint256) { return totalSupply_; } /** * @dev transfer token for a specified address * @param _to The address to transfer to. * @param _value The amount to be transferred. */ function transfer(address _to, uint256 _value) public returns (bool) { require(_to != address(0)); require(_value <= balances[msg.sender]); balances[msg.sender] = balances[msg.sender].sub(_value); balances[_to] = balances[_to].add(_value); emit Transfer(msg.sender, _to, _value); return true; } /** * @dev Gets the balance of the specified address. * @param _owner The address to query the the balance of. * @return An uint256 representing the amount owned by the passed address. */ function balanceOf(address _owner) public view returns (uint256) { return balances[_owner]; } } /** * @title Standard ERC20 token * * @dev Implementation of the basic standard token. * @dev https://github.com/ethereum/EIPs/issues/20 * @dev Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol */ contract StandardToken is ERC20, BasicToken { mapping (address => mapping (address => uint256)) internal allowed; /** * @dev Transfer tokens from one address to another * @param _from address The address which you want to send tokens from * @param _to address The address which you want to transfer to * @param _value uint256 the amount of tokens to be transferred */ function transferFrom(address _from, address _to, uint256 _value) public returns (bool) { require(_to != address(0)); require(_value <= balances[_from]); require(_value <= allowed[_from][msg.sender]); balances[_from] = balances[_from].sub(_value); balances[_to] = balances[_to].add(_value); allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value); emit Transfer(_from, _to, _value); return true; } /** * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender. * * Beware that changing an allowance with this method brings the risk that someone may use both the old * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * @param _spender The address which will spend the funds. * @param _value The amount of tokens to be spent. */ function approve(address _spender, uint256 _value) public returns (bool) { allowed[msg.sender][_spender] = _value; emit Approval(msg.sender, _spender, _value); return true; } /** * @dev Function to check the amount of tokens that an owner allowed to a spender. * @param _owner address The address which owns the funds. * @param _spender address The address which will spend the funds. * @return A uint256 specifying the amount of tokens still available for the spender. */ function allowance(address _owner, address _spender) public view returns (uint256) { return allowed[_owner][_spender]; } /** * @dev Increase the amount of tokens that an owner allowed to a spender. * * approve should be called when allowed[_spender] == 0. To increment * allowed value is better to use this function to avoid 2 calls (and wait until * the first transaction is mined) * From MonolithDAO Token.sol * @param _spender The address which will spend the funds. * @param _addedValue The amount of tokens to increase the allowance by. */ function increaseApproval(address _spender, uint _addedValue) public returns (bool) { allowed[msg.sender][_spender] = allowed[msg.sender][_spender].add(_addedValue); emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]); return true; } /** * @dev Decrease the amount of tokens that an owner allowed to a spender. * * approve should be called when allowed[_spender] == 0. To decrement * allowed value is better to use this function to avoid 2 calls (and wait until * the first transaction is mined) * From MonolithDAO Token.sol * @param _spender The address which will spend the funds. * @param _subtractedValue The amount of tokens to decrease the allowance by. */ function decreaseApproval(address _spender, uint _subtractedValue) public returns (bool) { uint oldValue = allowed[msg.sender][_spender]; if (_subtractedValue > oldValue) { allowed[msg.sender][_spender] = 0; } else { allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue); } emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]); return true; } } /** * @title SimpleToken * @dev Very simple ERC20 Token example, where all tokens are pre-assigned to the creator. * Note they can later distribute these tokens as they wish using `transfer` and other * `StandardToken` functions. */ contract BitNewsToken is StandardToken { string public name = "BitNews Token"; string public symbol = "BTN"; uint256 public decimals = 8; uint256 public INITIAL_SUPPLY = 100000000000000000;//10亿 /** * @dev Contructor that gives msg.sender all of existing tokens. */ constructor() public { totalSupply_ = INITIAL_SUPPLY; balances[msg.sender] = INITIAL_SUPPLY; } }
区块链
2019-12-02 16:32:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
最近在研究 区块链 涉及的各类学科,由于涉及的内容较多,如果所有学科内容全部了解一遍有点太多困难,感兴趣的人可以了解跟区块链相关的知识即可。
对于计算机科学中数据结构,用户需要熟悉主要数据结构的特性和复杂性保证,这样更好地了解其工作方式;密码学中主要了解散列函数(即哈希函数)、非对称加密(公私钥的关系、椭圆曲线),知道这些内容的基本概念;网络中要了解p2p网络,区块链的分布式在很大程度上源于其点对点网络拓扑结构,区块链是过去 p2p 网络的直接产物,要了解区块链通信模型则需要了解计算机网络的基础知识。而经济学,则是由于区块链项目中涉及各类经济模型的设计,与经济学密切相关。
如果真的对于区块链感兴趣,首先将中本聪的论文通读几遍,对于不同的地方再去查询资料,有目标的学习可能更好地去掌握。在对区块链有基本的概念后,再研究以太坊,然后去研究其他的项目。
区块链
2019-12-02 14:09:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
区块链是分布式数据存储、点对点传输、共识机制、加密算法等计算机技术的新应用模式。数据存储在增长链上的块中,而不是文件中。然后,密码签名用于按时间顺序链接到下一个生成的块。因此,链接的数据不会被篡改,所有参与者都可以看到所有交易记录。这些特点使区块链成为不同组织之间分享与合作的“书”。
最近流行的“区块链养猪”可信吗? 最近,“区块链”火了。从居高不下的热度中,可以感受到企业、机构对区块链技术和产业发展的热情,但一些地方出现的“虚火”过旺、操作跑偏等现象也不容忽视。 哎,大姨,这两天猪肉都快吃不起了 害!这有啥 我老乡推荐的 用区块链虚拟养猪 过个几天就有人买,我们躺着挣钱 殊不知,这却是打区块链幌子的骗局 “区块链”诈骗手段屡见不鲜,作为一种全新的数据管理方式,区块链技术凭借去中心化、可追溯等优势,有广泛的应用前景。 然而,伴随着区块链的热潮,社会上也出现了种种乱象。从金融诈骗到非法集资,再到非法传销,打着“区块链”的旗号从事违法活动的各种骗局引发公众的广泛关注。 比如,有的人怀着爆炒心态、暴富心理,采取各种手段花式蹭热点,明明自身业务和区块链八竿子打不着,硬要安上区块链名号以大肆炒作;有的宣扬“数字货币就是区块链”“炒币获官方支持”等谬论,热炒比特币、归零币、空气币等。 更有甚者,更多货币代码 www .gendan5.com ,打着区块链的幌子,包装出所谓“区块链养猪”“区块链鸡肉”“区块链走路”等项目招摇撞骗,行非法集资、传销、诈骗之实。 不久前,一款自称“基于区块链技术开发”的运动APP被有关部门立案调查。给传销手段披上“区块链”的外衣,并非个案。 种种“套路”损害了公众利益,更污染了区块链行业生态。倘若任由乱象丛生、坏了风气,让投机取巧者大行其道、踏实做事者举步维艰,势必造成“劣币驱逐良币”效应,对行业的健康和长远发展是很不利的。 好经莫要念歪了,区块链不能成为炒作的“噱头”、行骗的“招牌”,区块链发展更不能陷入急功近利、热衷赚“快钱”的歧途。
区块链
2019-11-29 17:01:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
SimpleChain “ 链盒 ”是区块链创业者的启发宝库,也是普通民众们的区块链实操指南。
区块链从技术构想走入现实,已日益显现出赋能产业革新和助推经济建设的伟力。政策风向充分体现了国家对区块链技术发展现状的准确把握,也为我国区块链产业发展指明了方向,展示了高瞻远瞩的战略判断。而抢占抢占区块链创新制高点,需要有扎实的理论研究与雄厚的人才积累。因此SimpleChain“ 链盒 ”也就应运而生,从理论基础与实践操作两个方面同时着手,即能启发广发区块链创业的创意才思,也可以让普通人上手实操深奥难懂的区块链产品。
SimpleChain“链盒”中有两本区块链书籍和一台SimpleNode X1智能算力硬件。用户先从《区块链与人工智能——数字经济新时代》理论基础入手,同时辅以《区块链实验环境操作指南(红宝书)》实操指南,最后上手实际操作SimpleNode X1智能算力硬件,即刻体验新数字经济下的区块链“黑科技”。
《区块链与人工智能》是畅销书《区块链与新经济:数字货币2.0时代》全新修订升级版。本书是市场上为数 不多的系统阐述区块链、人工智能技术与产业的入门级系统教程。从比特币到各类数字货币(代币),从基础原理到应用探讨,全景式呈现区块链与人工智能的发展脉络,既有历史的厚重感也有科技的未来感。本书的另一个亮点是系统整理了区块链创业地图,是一本关于区块链创业、应用、媒体的学习指南,以太坊创始人Vitalik专门作序。
区块链实验环境操作指南(红宝书)以SimpleChain为区块链实操范例,分别从SimpleChain技术特点与经济模型、基金会简介、生态入口、算力节点、通证流通、社区建设、开发者指南、报道文章等方面全维度地对SimpleChain进行深度解析。
SimpleNode X1智能算力硬件由香港Calforce Holding Limited推出,国内顶尖算力硬件研发团队独立打造,SimpleChain团队提供核心算法支持。机型算力为2M,功耗为5W,算力功耗比是同等显卡的数百倍,支持USB即插即用功能,适用多操作系统,是基于SimpleChain研发的新一代算力硬件,可为SimpleChain底层网络提供强大的算力节点支持。
区块链
2019-11-29 14:16:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
人们攻击说数字货币挖矿消耗了太多的能源,解决这个问题的办法不是去搞POS,而是提供革命性的能源,将能源的价格降低一倍使所有其它能源转化方式失去意义,让攻击造币耗能的人闭嘴。不要认为这不可能,只要挖矿造币一直耗能一直有利可图这就是必然的(可能会出现革命性的有能力用降低一半价格为全球供能的能源公司,这样的公司售卖能源的活动必然会绑定数字货币)。无论什么力量都是无法阻挡历史的车轮的,挖矿造币活动不是为了浪费能源,而是为了消耗人类总能力的一半,让人类有能力只用一半的能力就足以让社会运作,从而开启文明新纪元,踏过1.0。
区块链
2019-11-28 17:28:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
数据仓库的建设是“数据智能”必不可少的一环,也是大规模数据应用中必然面临的挑战。在智能商业中,数据的结果代表了用户反馈、获取数据的及时性尤为重要。快速获取数据反馈能够帮助公司更快地做出决策,更好地进行产品迭代,实时数仓在这一过程中起到了不可替代的作用。
如何更好的建设实时数仓、有哪些优秀的生产实践经验可借鉴?
11月28-30日,Flink Forward Asia 邀请来自 Netflix、美团点评、小米、OPPO、菜鸟等数仓专家,聚焦 Flink 实时数仓在数据链路中扮演的角色与在智能商业中的重要价值,分享实时数仓的应用实践及平台智能化的探索与思考。
美团点评基于 Apache Flink 的实时数仓平台实践
鲁昊 | 美团点评高级技术专家
美团点评的业务众多,涉及几十条业务线;数据量大,处理峰值达到 1.5 亿条每秒,每天数据增长量超过 3 万亿条;大多数业务都是交易场景,链路长、状态多样,业务在数仓建设中面临着很大挑战。随着业务对时效性的要求越来越高,如即时配送、实时营销,越来越多的业务对实时数仓提出了需求和探索。实时计算团队调研汇总了多个业务线在实时数仓方面的建设经验,建设了一站式的实时数仓开发平台,以更好得支持业务发展。
本次分享将主要介绍实时计算的业务应用和规模、多个业务在实时数仓方面的建设情况,以及基于 Flink 的实时计算平台和实时数仓平台。
小米流式平台架构演进与实践
夏军 | 小米流式平台负责人,高级研发工程师
小米集群业务线众多,从信息流,电商 ,广告到金融等覆盖了众多了领域,小米流式平台为小米集团各业务提供一体化的流式数据解决方案,主要包括数据采集,数据集成和流式计算三个模块。目前每天数据量达到 2 万亿条,实时同步任务 1.5 万,实时计算的数据 1 万亿条。伴随着小米业务的发展,流式平台也经历三次大升级改造,满足了众多业务的各种需求。
最新的一次迭代基于 Apache Flink,对于流式平台内部模块进行了彻底的重构,同时小米各业务也在由 Spark Streaming 逐步切换到 Flink。本次分享主要包括小米流式平台架构演进、基于 Flink 的新版本流式平台架构设计与产品化,小米典型业务应用实践,未来挑战与规划等。
Netflix:Evolving Keystone to an Open Collaborative Real-time ETL Platform
徐振中 | Senior Software Engineer at Netflix
Netflix 致力于我们会员的喜悦。我们不懈地专注于提高产品体验和高质量内容。近年来,我们一直在技术驱动的 Studio 和内容制作方面进行大量投资。在这个过程中,我们发现在实时数据平台的领域里中出现了许多独特并有意思的挑战。例如,在微服务架构中,Domain object 分布在不同的 App 及其有状态存储中,这使得低延迟高一致性的实时报告和 entity 搜索发现特别具有挑战性。
在本次演讲中,我们将讨论一些有趣的案例,分享分布式系统基础方面的各种挑战以及解决方案。我们还将讨论在开发运维过程中的收获,对开放式自助式实时数据平台的一些新愿景,以及我们对 Realtime ETL 基础平台的一些新思考。
菜鸟供应链实时数仓的架构演进及应用场景
贾元乔 | 菜鸟高级数据技术专家
贾元乔老师就职于菜鸟网络供应链数据团队,致力于菜鸟供应链数仓建设、数据产品开发以及数据技术创新。
本次分享主要从数据模型、数据计算、数据服务等几个方面介绍菜鸟供应链数据团队在实时数据技术架构上的演进,以及在供应链场景中,典型的实时应用场景及Flink实现方案。
OPPO 基于 Apache Flink 的实时数仓实践
张俊 | Apache Flink Contributor,OPPO大数据平台研发负责人
张俊老师主导了 OPPO 涵盖“数据接入-数据治理-数据开发-数据应用”全链路的数据中台建设。曾先后工作于摩根士丹利、腾讯,具有丰富的数据系统研发经验,目前重点关注数仓建设、实时计算、OLAP引擎方向,同时也是Flink开源社区贡献者。本次演讲主要分享 OPPO 基于 Flink 构建实时数仓的:
1.建设背景
2.顶层设计
3.落地实践
4.未来展望


原文链接
本文为云栖社区原创内容,未经允许不得转载。
区块链
2019-11-28 17:14:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
现在网络上都有很多查找视频资源的网站和工具,而且大部分网站和工具都是提供MKV视频格式和MP4视频格式的。网上还会出现一种一种视频格式,WEBM视频格式。这个WEBM格式画面清晰而且比特率也比较低。也就是说同样参数的视频文件,可能WEBM格式的视频会占用更小的内存。所以今天教大家如何把MP4视频格式快速转换成WEBM视频。
下面使用两种方法转换视频格式:
第一种:修改后缀名
1、最简单的方法就是直接修改名称。但是这个方法并不是所以的格式都可以这么做,有些修改后会打不开。选择MP4视频然后右键重命名将MP4格式改成WEBM格式即可。
第二种:专业的视频转换器
1、在使用专业的视频转换器之前还是需要先安装软件的。在迅捷视频官网中把迅捷视频转换器的安装文件下载到本地,然后需要设置安装的位置,然后就可以点击立即安装了。不然就会安装到C:\Program Files (x86)\videconverter路径中。
2、然后就是打开软件进行下一步的操作了。可以看到有很多的功能提供给我们使用和操作的。不过这里需要转换视频的格式,所以直接点击视频转换,然后进入其对应的转换页面中。至于其他的功能之后可以使用的。
3、然后就可以看到空白一片的操作界面,现在就需要把MP4视频添加到软件中了。点击添加文件按钮然后选择下载完成的MP4视频导入其中。或者使用添加文件夹的方法以及拖拽视频也能够完美导入视频文件。
4、然后就可以设置转换输出的文件格式了。软件之默认转换成MP4格式,而此次转换的源文件也是MP4格式,如果不做修改是不能转换格式的。所以在输出格式中选择WEBM—同原文件,这就把视频格式和分辨率都设置完成了。
5、如果觉得这些视频分辨率太少,无法满足自己的需求,那么,可以点击添加自定义设置,然后再进入自定义参数设置面板中设置更多更详细的输出文件参数。包含帧数、分辨率、比特率、取样频率和声道等众多参数。
6、然后就是找一个地方保存转换的视频文件。点击更改路径,然后再在浏览文件夹的对话框中设置保存地址。选择完成后可以点击打开文件夹进行确认是否成功设置保存地址。
7、最后就可以转换视频格式了。点击软件左下角的全部转换,然后只需要等待软件把MP4视频格式转换成WEBM视频就可以打开播放了。转换的进度可以参考进度条到100%。然后点击打开按钮即可直接到达保存视频的位置了。
以上就是使用两种方法将MP4视频格式快速转换成RMVB视频的教程了。如果想要更方便的转换视频格式,可以使用迅捷视频官网的在线WEBM转换MP4格式的功能。不过迅捷视频转换器支持更多的文件格式转换。
想要了解更多有关MP4视频格式如何快速转换成WEBM格式的相关信息可以访问:https://www.xunjieshipin.com/8441
区块链
2019-11-28 10:33:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
Polkadot是一个网络协议,能够传递任何数据(不只限于代币)到所有区块链。这意味着Polkadot是一个真正的多链应用环境,使跨链注册和跨链计算等类似操作成为可能。IPSE是面向IPFS网络的搜索引擎,底层采用分布式存储思路,但token依赖于EOS网络。一个支持跨链的系统将有利于不同网络之间的资产交换和互操作。

IPSE的2.0网络将使用Substrate,并和Polkadot网络完成连接。Polkadot能传递数据到公共、开放、公开的区块链和私有或联盟链,这使得构建从私有链获得许可数据并在公有链上使用的应用程序成为可能。

Polkadot网络结构
1.平行链:特定应用的区块链
平行链是包含Polkadot网络的可并行的区块链(“para-chains”)。每个平行链都可以拥有最适合其应用的独特架构。 平行链还用于并行事务处理并实现可伸缩性。平行链通过中继链通讯和保证安全。

2.中继链: 连接和验证平行链的区块
中继链是Polkadot网络的核心,它确保平行链 和平行链之间传递信息。信息可以是 交易或任何类型数据。

3.桥接链: 连接Polkadot到其它外部区块链
桥接链是特殊的平行链,它允许与其它不是 经Polkadot中继链保护,而是使用 自己安全性的区块链通信。 (例如:比特币,以太坊)。

Polkadot网络中的角色
A.验证人:产生中继链的区块
验证人运行全节点并负责验证和增加区块到 中继链。它从校对人接收和核对潜在的平行链 区块并且加入有效的区块头到中继链。

B.校对人: 在平行链上打包交易
校对人将它们监视的平行链上的事务打包(或整理)成块,并将此块的证明发送给验证者。校对者也可以充当验证者。

C.提名人: 提名验证人
提名者提出权益,并选择验证者代表他们的权益。当提名者选择的验证者受到奖励或惩罚时,提名者将得到相应的奖励或惩罚。

并行处理交易
由于连接到Polkadot的平行链都是专门的区块链, 每个平行链都具有独特的特征和自治的主权。IPSE将构建平行链,形成多链的生态。
这样的好处是,链的交互是并行处理的,从而实现了高度可扩展的系统。IPSE既可以保持原有的特性,又能实现网络自治,并能实现共享安全性。同时,事务可以跨链分布,允许在同一时间段内处理更多事务。
区块链
2019-11-28 10:14:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
我认为学习计算机语言,应该先用后学,这一节,我们来实现一个猜数字的小游戏。
先简单介绍一个这个游戏的内容:游戏先生成一个1到100之间的任意一个数字,然后我们输入自己猜测的数字,游戏会告诉我们输入的数字太大还是太小,然后我们重新输入新的数字,直到猜到游戏生成的数字,然后游戏结束。
创建项目
制作游戏的第一步先创建项目,创建方法和上一节一样,使用 cargo 来创建一个名为 guessing_game 的项目。 cargo new guessing_game && cd guessing_game
项目创建完成,可以运行一下,如果程序打印出 Hello, World! 则证明程序创建完成,运行命令如下: cargo run
读取猜测的数字
正式写游戏的第一步,让游戏先读取我们猜测的数字。我们可以先把打印语句换成提示我们输入数字的提示语句。 use std::io; fn main() { println!("猜测数字游戏,请输入您猜测的数字。"); let mut guess = String::new(); io::stdin().read_line(&mut guess).expect("读取数字失败!"); println!("您猜测的数字是:{}", guess); }
这段代码包含了大量的信息,我们一行一行地过一遍。 1.因为我们需要读取用户的输入,然后把它作为结果打印出来,所以需要把 标准库(被称作 std )中的 io 依赖引入当前作用域。 2.在主函数中写方法体,首先是打印提示语,不说了。 3.然后创建一个用于保存即将输入的字符串的 String 类型的变量 guess。 4.把控制台输入的数字读取到变量 guess 中,如果读取失败,则打印 “读取数字失败!” 的字符串。 5.把读取的数字再打印到控制台。
注:这段程序的细节暂时先不深究了,后续文章会一一解释清楚。
测试一下这段程序: cargo run Compiling guessing_game v0.1.0 (/Users/shanpengfei/work/rust-work-space/study/guessing_game) Finished dev [unoptimized + debuginfo] target(s) in 1.01s Running `target/debug/guessing_game` 猜测数字游戏,请输入您猜测的数字。 2 您猜测的数字是:2
生成随机数
我们的游戏需要创建一个随机数,供我们去猜测,这个数字要求每次启动游戏时都是不相同的,这样游戏才更加有意思。接下来我们在游戏中生成一个1到100的随机数。但是 rust 没有在它的标准库中提供生成随机数的方法,不过没关系,它提供了生成随机数的名为 rand 的 crate。我们来引入一下生成随机数的 crate,修改 Cargo.toml 文件: [dependencies] rand = "^0.3.14"
只需要在 [dependencies] 下面添加需要的 crate 即可。这次添加的 crate 名字是 rand,版本号 0.3.14, 而 ^ 的意思是兼容 0.3.14 版本的任何版本都可以。然后我们编译一下程序,就会自动下载引入的依赖: cargo build Updating crates.io index Compiling libc v0.2.65 Compiling rand v0.4.6 Compiling rand v0.3.23 Compiling guessing_game v0.1.0 (/Users/shanpengfei/work/rust-work-space/study/guessing_game) Finished dev [unoptimized + debuginfo] target(s) in 1m 13s
引入了生成随机数和 crate 后,我们来生成一下需要的 crate,代码如下: use std::io; use rand::Rng; fn main() { let secret_number = rand::thread_rng().gen_range(1, 101); println!("生成的随机数字是:{}", secret_number); println!("猜测数字游戏,请输入您猜测的数字。"); let mut guess = String::new(); io::stdin().read_line(&mut guess).expect("读取数字失败!"); println!("您猜测的数字是:{}", guess); }
可以看到我们在前面代码的基础上添加了三行代码: 1.第一行是引入生成随机数的依赖。 2.第二行是生成一个随机数,随机数的范围是 [1, 101),区间是左闭右开,说人话就是1到100。 3.第三行是打印生成的随机数。 然后我们测试一下添加的随机数是否生效: cargo run Compiling guessing_game v0.1.0 (/Users/shanpengfei/work/rust-work-space/study/guessing_game) Finished dev [unoptimized + debuginfo] target(s) in 0.45s Running `target/debug/guessing_game` 生成的随机数字是:79 猜测数字游戏,请输入您猜测的数字。 6 您猜测的数字是:6
比较随机数和猜测数
现在我们可以输入自己猜测的数字,也可以生成随机数字了,那么接下来就是比较二者的大小了。但是在比较之前还有个问题,控制台输入的数字是 string 类型的,而随机生成的数字是无符号32位整型(u32),二者不类型不一致,不能作比较,因此,在比较之前,我们应该先把控制台输入的 string 类型的数字转成u32类型的,代码如下: use std::io; use std::cmp::Ordering; use rand::Rng; fn main() { let secret_number = rand::thread_rng().gen_range(1, 101); println!("生成的随机数字是:{}", secret_number); println!("猜测数字游戏,请输入您猜测的数字。"); let mut guess = String::new(); io::stdin().read_line(&mut guess).expect("读取数字失败!"); let guess: u32 = guess.trim().parse().expect("请输入一个数字!"); println!("您猜测的数字是:{}", guess); match guess.cmp(&secret_number) { Ordering::Less => println!("您猜测的数字太小了!"), Ordering::Greater => println!("您猜测的数字太大了!"), Ordering::Equal => println!("恭喜您,猜对了!"), } }
可见,我们在三个位置添加了代码: 1.从标准库中添加了比较的依赖。 2.把输入的数字类型成u32类型,如果输入的不是数字,则转换失败,打印出错误信息。 3.最后一部分就是比较一下二者的大小,并打印出比较的结果。 好了,我们先测试一下吧,这里我们只测正确的输入: cargo run  101 ↵ Compiling guessing_game v0.1.0 (/Users/shanpengfei/work/rust-work-space/study/guessing_game) Finished dev [unoptimized + debuginfo] target(s) in 0.42s Running `target/debug/guessing_game` 生成的随机数字是:53 猜测数字游戏,请输入您猜测的数字。 4 您猜测的数字是:4 您猜测的数字太小了!
添加循环
我们发现,我们只输入了一次,游戏就结束了,这显然不符合我们的预期。我们的预期是,我们可以一直猜一直猜,直到猜中才让游戏结束,那应该怎么修改一下呢?添加一个循环,代码如下: use std::io; use std::cmp::Ordering; use rand::Rng; fn main() { let secret_number = rand::thread_rng().gen_range(1, 101); println!("生成的随机数字是:{}", secret_number); loop { println!("猜测数字游戏,请输入您猜测的数字。"); let mut guess = String::new(); io::stdin().read_line(&mut guess).expect("读取数字失败!"); let guess: u32 = guess.trim().parse().expect("请输入一个数字!"); println!("您猜测的数字是:{}", guess); match guess.cmp(&secret_number) { Ordering::Less => println!("您猜测的数字太小了!"), Ordering::Greater => println!("您猜测的数字太大了!"), Ordering::Equal => println!("恭喜您,猜对了!"), } } }
这里修改得比较简单,只需要添加一个名叫 loop 的关键字,然后把需要循环的内容放在 {} 中即可,然后我们测试一下: cargo run Compiling guessing_game v0.1.0 (/Users/shanpengfei/work/rust-work-space/study/guessing_game) Finished dev [unoptimized + debuginfo] target(s) in 0.38s Running `target/debug/guessing_game` 生成的随机数字是:71 猜测数字游戏,请输入您猜测的数字。 50 您猜测的数字是:50 您猜测的数字太小了! 猜测数字游戏,请输入您猜测的数字。 71 您猜测的数字是:71 恭喜您,猜对了! 猜测数字游戏,请输入您猜测的数字。 45 您猜测的数字是:45 您猜测的数字太小了! 猜测数字游戏,请输入 t thread 'main' panicked at '请输入一个数字!: ParseIntError { kind: InvalidDigit }', src/libcore/result.rs:1165:5 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
我们的游戏可以多次输入了,但是有没有发现一些问题呢? 1.游戏直接告诉我们生成的数字了,那就不用猜了,直接输入就好了。 2.当我们猜对后,游戏没有结束。 3.当我们输入的内容不是数字的时候,才会结束游戏,而且不仅打印了我们预期的错误信息,还打印了其它信息。 接下来,我们把这些问题依次修改,代码如下: use std::io; use std::cmp::Ordering; use rand::Rng; fn main() { let secret_number = rand::thread_rng().gen_range(1, 101); // println!("生成的随机数字是:{}", secret_number); loop { println!("猜测数字游戏,请输入您猜测的数字。"); let mut guess = String::new(); io::stdin().read_line(&mut guess).expect("读取数字失败!"); let guess: u32 = match guess.trim().parse() { Ok(num) => num, Err(_) => continue, }; println!("您猜测的数字是:{}", guess); match guess.cmp(&secret_number) { Ordering::Less => println!("您猜测的数字太小了!"), Ordering::Greater => println!("您猜测的数字太大了!"), Ordering::Equal => { println!("恭喜您,猜对了!"); break; } } } }
这三处错误的修改方式依次是: 1.把打印随机数的代码注释掉。 2.在做类型转换时,使用 match 关键字作判断,如果转化成功,则返回转化后的结果,如果转化失败,不管因为什么原因失败,都直接跳出本次循环。 3.在做二个数字大小判断时,如果判断相等,则结束循环。 我们来测试一下修改的结果: cargo run Compiling guessing_game v0.1.0 (/Users/shanpengfei/work/rust-work-space/study/guessing_game) Finished dev [unoptimized + debuginfo] target(s) in 0.38s Running `target/debug/guessing_game` 猜测数字游戏,请输入您猜测的数字。 50 您猜测的数字是:50 您猜测的数字太小了! 猜测数字游戏,请输入您猜测的数字。 r 猜测数字游戏,请输入您猜测的数字。 75 您猜测的数字是:75 您猜测的数字太小了! 猜测数字游戏,请输入您猜测的数字。 87 您猜测的数字是:87 您猜测的数字太大了! 猜测数字游戏,请输入您猜测的数字。 81 您猜测的数字是:81 恭喜您,猜对了!
可以看到我们的游戏制作完成了~~
欢迎阅读单鹏飞的学习笔记
区块链
2019-11-27 19:59:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
最近发现很多区块链项目团队有一些非常明显的问题,例如没有自己的方向和目标,没有紧迫感和创新性。
其实,目前区块链技术真的存在很多很多问题,例如 公链项目 涉及的跨链、合适的落地场景、便捷性、生态如何扩大,联盟链如何更好地控制权限、保障数据安全等等,像提升tps是所有区块链项目都需要解决的问题之一。
相对而言,公链需要研究的内容和待解决的问题比联盟链多很多,由于联盟链中加入节点和权限都有控制,所以链上数据的完全性、开放性、控制性更加简单,而公链中很多问题没有办法直接解决,比如链上被写入不好的信息,由于公链是完全开放的,节点没有办法控制整个链,根本没有办法处理链上数据,只能通过屏蔽区块链浏览器上某些内容来实现。
如果真的选择研究区块链技术、参与区块链开发,首先订好目标、方向和希望解决的问题,不然,可能很久之后并没有获得突破性进展和结果,自己的付出没有得到回报。
区块链
2019-11-27 17:33:01
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
11月24日,比原链CTO James参加了Go中国举办的Gopher Meetup杭州站活动,与来自阿里、网易的技术专家带来Kubernetes、区块链、日志采集、云原生等话题的分享。James向大家介绍了Go语言特性在区块链中的应用还分析了Go语言成为区块链主流开发语言的原因。
比原链的系统架构
在区块链系统中内核层是最核心的,他承接了区块验证、交易验证、节点维护、打包挖矿等重多职责。通信层掌管了区块链系统的网络服务,区块链的网络更像P2P的网络形式,他呈网状扩散,负责区块同步、交易同步、节点发现等重要的功能。钱包层是直接和用户发生交互的一层,他的职责是资产管理、私钥管理,并与内核层通信验证区块交易。
以Bytom为例,他的内核层分为了五个的模块。我们举例描述几个主要的模块。
孤儿块管理:孤儿块就是由矿工挖出但未成为主链区块的区块(在相同高度产生2个甚至更多的合法区块,一个区块成为主链,剩下的则称为孤儿块),孤儿块管理就是将未成为主链区块的孤儿块存储起来。举个例子,我现在挖到的区块是100,那么下一个区块理论上是101,但是在网络层发生延时的时候,可能会发生先出102再出101的情况,那么孤儿块管理会将这些父块未到的子块先缓存起来。
共识层:确认一个块是否合法。分为区块头验证和交易验证。区块头验证需要验证它的父块和时间戳,同是需要算力来保证记账权利。交易验证比原特别的设计了一层BC层,这层在交易验证时会获得更好的性能,交易验证还和智能合约相关,交易被验证时参数会参入虚拟机验证该交易是否合法。
区块树管理:又称为Block Index,作用是记录全网所有的块,保存了全网所有块的一张镜像图。因为有孤儿块,所有它并不是链式结构的,会有分叉的情况,所以称为区块树。举个例子,区块树管理好比有一个分布式系统,但无法保证每个节点的状态一致,可能会出现同一个高度产生同时参生区块的情况。区块树管理就是具备了在节点状态不一致的情况下让系统回滚到正确的区块这个功能。
数据存储:将区块数据做持久化存储。包含两种数据,第一种是区块数据,会在网络上进行广播的原生区块信息;第二种是UTXO数据,存储UTXO数据是为了更快的验证一笔UTXO是否可以花费,而不需要去遍历所有区块信息。
交易池:维护了所有全网发出的但是还未被确认的交易。跟它关联最大的是挖矿模块,挖矿模块每次要产生一个新区块的时候,它会从交易池拿一些交易打包成块,然后用Tensority共识算法进行工作量验算。举个例子,在节点打包交易之前,交易处在一个未确认的状态之下,交易池会将这些未确认的交易保存起来,分配给后面的矿工用于打包。
WHY GOLANG?
第一点,区块链是多模块异步协同工作的,分成了P2P层、钱包层、内核层。其中内核层、情报层里面都有不同的很多子模块,在负责不同的事情。Go语言做得很出色非常适合做这方面的开发。
第二点,区块链项目有核心团队但是主要还是依赖社区参与,Go语言编译上相对于其他语言稍微严格一点,在制定规范后可以使不同开发者代码风格相近,有利于协同工作的展开。
第三点,Go语言社区完善,有很多非常好的开源库支持,使用起来非常方便用户体验良好。
第四点,主流语言的头部效应,在区块链的项目里面超过85%的项目都是基于Go语言开发的,大部分区块链工程师都擅长Go语言,所以当新的项目开始的时候,会首选Go语言。
对区块链感兴趣的程序员可以投递简历至:james@bytom.io
区块链
2019-11-26 17:44:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
最近的币圈可谓人心惶惶,自上海金融办整治境内非法经营的交易所和数字货币非法融资行为以来,各地也纷纷出台相应政策。实际上,最先出现问题的基本上都是经营过程中以区块链作为概念涉及诈骗传销的主体,和区块链实际上没有任何关系,这也让火币收紧了上币业务的范围,收缩到了技术特点或商业模式出众的币种。
在我看来,这一波清理整顿实属行业之幸,已经有太多的非法活动透支了区块链行业了,清理整顿有利于更高地推动具有价值的创新,我甚至认为,token在特定范围内加速资源有效配制的功能也是会被肯定的。而同时,在境内真正的数字货币可能将来只能是DCEP,剩下的就是纳入证券法监管的证券形token以及需要自律的功能性token,届时,没有发生过融资融币行为并且具有独立技术的创新区块链项目,例如 SIPC 将会迎来真正的行业红利期。
区块链
2019-11-25 11:34:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
部署并运行 Java 链代码示例
您已经定义并启动了本地区块链网络,而且已构建 Java shim 客户端 JAR 并安装到本地 Maven 存储库中,现在已准备好在之前下载的 Hyperledger Fabric 附带的一个 Java 链代码示例上构建、注册和调用交易。
部署并运行链代码
您将执行以下步骤: 使用 Gradle 构建示例。 通过运行 Gradle 构建软件为您创建的脚本,向验证对等网络注册该示例。 使用 SoapUI 将示例部署到本地区块链网络。 使用 SoapUI 在示例链代码上调用交易。
1.构建示例
导航到 $GOPATH/src/github.com/hyperledger/fabric/examples/chaincode/java/Example 目录。
接下来,通过命令行,使用此命令启动 Gradle 构建软件: gradle -b build.gradle build
您会看到以下输出: $ cd GOPATH/src/github.com/hyperledger/fabric/examples/chaincode/java/Example $ gradle -b build.gradle build Starting a Gradle Daemon (subsequent builds will be faster) :examples:chaincode:java:Example:compileJava :examples:chaincode:java:Example:processResources UP-TO-DATE :examples:chaincode:java:Example:classes :examples:chaincode:java:Example:jar :examples:chaincode:java:Example:startScripts :examples:chaincode:java:Example:distTar :examples:chaincode:java:Example:distZip :examples:chaincode:java:Example:assemble :examples:chaincode:java:Example:compileTestJava UP-TO-DATE :examples:chaincode:java:Example:processTestResources UP-TO-DATE :examples:chaincode:java:Example:testClasses UP-TO-DATE :examples:chaincode:java:Example:test UP-TO-DATE :examples:chaincode:java:Example:check UP-TO-DATE :examples:chaincode:java:Example:build :examples:chaincode:java:Example:copyToLib BUILD SUCCESSFUL Total time: 6.935 secs
该构建过程通过两种形式创建了一个位于目录 build/distributions 中的独立发行版:TAR 文件和 ZIP 文件,每个文件都包含运行链代码所需的所有资源,其中包括一个用于驱动链代码的名为 Example 的脚本。
Example 链代码现在已准备好向本地区块链网络注册。
2.注册示例
确保本地区块链网络正在运行。如果未运行,则需要启动它。如果需要温习一下相关内容,请参阅“ 启动区块链网络 ”部分。
如果您未在 $GOPATH/src/github.com/hyperledger/fabric/examples/chaincode/java/Example 目录下,请导航到这里。
接下来,将 Example.zip(或 Example.tar)解压到 build/distributions 目录中: $ cd $GOPATH/src/github.com/hyperledger/fabric/examples/chaincode/java/Example $ cd build/distributions/ $ unzip Example.zip Archive: Example.zip inflating: Example/lib/chaincode.jar inflating: Example/lib/grpc-all-0.13.2.jar inflating: Example/lib/commons-cli-1.3.1.jar inflating: Example/lib/shim-client-1.0.jar inflating: Example/lib/grpc-netty-0.13.2.jar inflating: Example/lib/grpc-auth-0.13.2.jar inflating: Example/lib/grpc-protobuf-nano-0.13.2.jar inflating: Example/lib/grpc-core-0.13.2.jar inflating: Example/lib/grpc-protobuf-0.13.2.jar inflating: Example/lib/grpc-okhttp-0.13.2.jar inflating: Example/lib/grpc-stub-0.13.2.jar inflating: Example/lib/protobuf-java-3.0.0.jar inflating: Example/lib/netty-tcnative-boringssl-static-1.1.33.Fork21-osx-x86_64.jar inflating: Example/lib/netty-codec-http2-4.1.0.CR3.jar inflating: Example/lib/google-auth-library-oauth2-http-0.3.0.jar inflating: Example/lib/guava-18.0.jar inflating: Example/lib/protobuf-javanano-3.0.0-alpha-5.jar inflating: Example/lib/jsr305-3.0.0.jar inflating: Example/lib/okio-1.6.0.jar inflating: Example/lib/okhttp-2.5.0.jar inflating: Example/lib/netty-codec-http-4.1.0.CR3.jar inflating: Example/lib/netty-handler-4.1.0.CR3.jar inflating: Example/lib/google-auth-library-credentials-0.3.0.jar inflating: Example/lib/google-http-client-1.19.0.jar inflating: Example/lib/google-http-client-jackson2-1.19.0.jar inflating: Example/lib/netty-codec-4.1.0.CR3.jar inflating: Example/lib/netty-buffer-4.1.0.CR3.jar inflating: Example/lib/netty-transport-4.1.0.CR3.jar inflating: Example/lib/httpclient-4.0.1.jar inflating: Example/lib/jackson-core-2.1.3.jar inflating: Example/lib/netty-common-4.1.0.CR3.jar inflating: Example/lib/netty-resolver-4.1.0.CR3.jar inflating: Example/lib/httpcore-4.0.1.jar inflating: Example/lib/commons-logging-1.1.1.jar inflating: Example/lib/commons-codec-1.3.jar inflating: Example/bin/Example inflating: Example/bin/Example.bat
您可能想知道 “为何有如此多的文件?”该发行版包含(在独立进程中)单独运行链代码所需的一切资源,以及所有依赖 JAR 文件。
要注册链代码示例,可在 build/distributions 文件夹中执行以下脚本: ./Example/bin/Example
这会运行一个独立进程来向本地区块链网络注册链代码示例。您会看到以下终端窗口输出: $ ./Example/bin/Example Hello world! starting [Ljava.lang.String;@7ef20235 Feb 22, 2017 10:05:08 AM example.Example main INFO: starting Feb 22, 2017 10:05:08 AM org.hyperledger.java.shim.ChaincodeBase newPeerClientConnection INFO: Inside newPeerCLientConnection Feb 22, 2017 10:05:08 AM io.grpc.internal.TransportSet$1 call INFO: Created transport io.grpc.netty.NettyClientTransport@3dd7b80b(/127.0.0.1:7051) for /127.0.0.1:7051 Feb 22, 2017 10:05:14 AM io.grpc.internal.TransportSet$TransportListener transportReady INFO: Transport io.grpc.netty.NettyClientTransport@3dd7b80b(/127.0.0.1:7051) for /127.0.0.1:7051 is ready
查看本地区块链网络的控制台,您会看到以下输出行: . . vp0_1 | 16:05:14.048 [chaincode] HandleChaincodeStream -> DEBU 06d Current context deadline = 0001-01-01 00:00:00 +0000 UTC, ok = false vp0_1 | 16:05:14.065 [chaincode] processStream -> DEBU 06e []Received message REGISTER from shim vp0_1 | 16:05:14.065 [chaincode] HandleMessage -> DEBU 06f []Handling ChaincodeMessage of type: REGISTER in state created vp0_1 | 16:05:14.065 [chaincode] beforeRegisterEvent -> DEBU 070 Received REGISTER in state created vp0_1 | 16:05:14.065 [chaincode] registerHandler -> DEBU 071 registered handler complete for chaincode hello vp0_1 | 16:05:14.065 [chaincode] beforeRegisterEvent -> DEBU 072 Got REGISTER for chaincodeID = name:"hello" , sending back REGISTERED . .
记下注册日志输出中的 chaincodeID name(示例中为 hello;如上面 第 8 行 所示)。以后在通过结构的 REST 接口部署 Example 链代码时,JSON 消息中需要使用此信息。
上面的输出表明 Example 链代码正在运行,而且已向本地区块链验证对等网络注册,并做好了部署准备。
3.部署示例
Hyperledger Fabric 提供了一个用于与该结构交互的 REST Web 服务接口。与 fabric 的第一次交互是部署链代码。确保本地区块链网络正在运行,然后启动 SoapUI,单击 REST 按钮创建一个新的 REST 项目。您会看到一个类似图 3 的对话框,在其中输入用于所有 REST 请求的基础 URL:
输入 http://localhost:7050 作为 URL,然后单击 OK。端口 7050 是 fabric 使用的默认 REST 端口,而且因为区块链网络是在本地计算机上运行的,所以将使用 localhost 作为主机名。
在 SoapUI 启动后,可以执行一次快速冒烟测试,以确保它能与本地区块链网络进行通信。展开刚创建的新的 REST 资源,直到看到 Request 1,然后在 Editor 窗口中打开它。使用 GET 方法,在 resource 下输入 /chain。确保单击了 output 选项卡上的 JSON 选项,然后运行请求(通过单击 arrow 图标)。执行此请求时,会在 Editor 窗口右侧的输出选项卡中返回当前区块的哈希值,如图 4 所示:
如果看到一条类似图 4 的 JSON 消息(当然您的网络的 currentBlockHash 值会有所不同),那么您已准备好部署 Example 链代码。
右键单击 REST Project 1 ( http://localhost:7050 ) 下的端点并选择 New Resource;您会看到一个包含 Resource Path 字段的 “New REST Resource” 对话框(参见图 5): 输入 /chaincode 作为 resource path,然后单击 OK,您会看到 SoapUI Projects 面板中显示了新资源。打开对此资源的请求(默认情况下该请求名为 Request 1),将方法更改为 POST,并将此 JSON 粘贴到请求编辑器窗口左下角的请求区域: { "jsonrpc": "2.0", "method": "deploy", "params": { "type": 1, "chaincodeID":{ "name": "hello" }, "CtorMsg": { "args": [""] } }, "id": 1 }
有 3 点需要注意:
第 3 行 :method 值必须为 deploy。 第 6-7 行 :JSON 消息中的 chaincodeID.name 必须与您在上一节中注册 Example 链代码时所用的 chaincodeID 匹配(在 Example 链代码中,该值为 hello)。 第 13 行 :id 值用于协调请求。本教程不需要过多地考虑它,但要注意的是,在响应中始终会发送回该值(参见下一个清单)。 提交此请求时,JSON 输出应如下所示: { "jsonrpc": "2.0", "result": { "status": "OK", "message": "hello" }, "id": 1 }
图 6 给出了 SoapUI 中的输出的屏幕截图。JSON 输出消息会显示在输出选项卡中,该选项卡位于请求编辑器的右侧。
终端窗口中的网络日志输出应包含以下行: . . vp0_1 | 20:48:39.482 [rest] ProcessChaincode -> INFO 0c4 REST processing chaincode request... vp0_1 | 20:48:39.482 [rest] processChaincodeDeploy -> INFO 0c5 REST deploying chaincode... vp0_1 | 20:48:39.483 [devops] Deploy -> DEBU 0c6 Creating deployment transaction (hello) vp0_1 | 20:48:39.483 [devops] Deploy -> DEBU 0c7 Sending deploy transaction (hello) to validator vp0_1 | 20:48:39.483 [peer] sendTransactionsToLocalEngine -> DEBU 0c8 Marshalling transaction CHAINCODE_DEPLOY to send to local engine vp0_1 | 20:48:39.483 [peer] sendTransactionsToLocalEngine -> DEBU 0c9 Sending message CHAIN_TRANSACTION with timestamp seconds:1487796519 nanos:483661510 to local engine vp0_1 | 20:48:39.483 [consensus/noops] RecvMsg -> DEBU 0ca Handling Message of type: CHAIN_TRANSACTION vp0_1 | 20:48:39.483 [consensus/noops] broadcastConsensusMsg -> DEBU 0cb Broadcasting CONSENSUS vp0_1 | 20:48:39.483 [peer] Broadcast -> DEBU 0cc Broadcast took 1.135s vp0_1 | 20:48:39.483 [consensus/noops] RecvMsg -> DEBU 0cd Sending to channel tx uuid: hello vp0_1 | 20:48:39.483 [rest] processChaincodeDeploy -> INFO 0ce Successfully deployed chainCode: hello vp0_1 | 20:48:39.484 [rest] ProcessChaincode -> INFO 0cf REST successfully deploy chaincode: {"jsonrpc":"2.0","result":{"status":"OK","message":"hello"},"id":1} . .
第 3-4 行 显示了输出,表明网络已收到部署消息,并且该结构正在部署链代码。 第 13-14 行 表明链代码已成功部署。
在运行链代码的终端窗口中,可以注意到以下输出: $ ./build/distributions/Example/bin/Example Hello world! starting [Ljava.lang.String;@7ef20235 Feb 22, 2017 2:44:43 PM example.Example main INFO: starting Feb 22, 2017 2:44:43 PM org.hyperledger.java.shim.ChaincodeBase newPeerClientConnection INFO: Inside newPeerCLientConnection Feb 22, 2017 2:44:43 PM io.grpc.internal.TransportSet$1 call INFO: Created transport io.grpc.netty.NettyClientTransport@46adccd3(/127.0.0.1:7051) for /127.0.0.1:7051 Feb 22, 2017 2:44:48 PM io.grpc.internal.TransportSet$TransportListener transportReady INFO: Transport io.grpc.netty.NettyClientTransport@46adccd3(/127.0.0.1:7051) for /127.0.0.1:7051 is ready Feb 22, 2017 2:48:40 PM example.Example run INFO: In run, function: Feb 22, 2017 2:48:40 PM example.Example run
我包含了所有上下文输出,在向区块链网络发送部署消息时,您会看到类似第 11-13 行 的消息。
4.在示例上调用交易
最后,将会调用 hello 方法,可以看到它会在运行链代码的终端窗口的日志消息中显示出来。
在 SoapUI 中的 chaincode 资源下,右键单击 Method 1 并选择 Clone Method。将该方法命名为 Invoke,然后单击 OK。打开新的 Invoke 方法下的 Request 1,并粘贴到以下 JSON 请求中: { "jsonrpc": "2.0", "method": "invoke", "params": { "type": 1, "chaincodeID":{ "name": "hello" }, "CtorMsg": { "args": ["hello"] } }, "id": 2 }
运行该请求时,会看到以下 JSON 响应: { "jsonrpc":"2.0", "result": { "status":"OK", "message":"1c1811d0-a958-4c58-ab1d-e1df550c18a3" }, "id":2 }
图 7 给出了 SoapUI 中的输出的屏幕截图
网络日志输出应包含以下行: . . vp0_1 | 21:44:35.143 [rest] ProcessChaincode -> INFO 555 REST processing chaincode request... vp0_1 | 21:44:35.143 [rest] processChaincodeInvokeOrQuery -> INFO 556 REST invoke chaincode... vp0_1 | 21:44:35.143 [devops] invokeOrQuery -> INFO 557 Transaction ID: 1c1811d0-a958-4c58-ab1d-e1df550c18a3 vp0_1 | 21:44:35.143 [devops] createExecTx -> DEBU 558 Creating invocation transaction (1c1811d0-a958-4c58-ab1d-e1df550c18a3) vp0_1 | 21:44:35.143 [devops] invokeOrQuery -> DEBU 559 Sending invocation transaction (1c1811d0-a958-4c58-ab1d-e1df550c18a3) to validator vp0_1 | 21:44:35.143 [peer] sendTransactionsToLocalEngine -> DEBU 55a Marshalling transaction CHAINCODE_INVOKE to send to local engine vp0_1 | 21:44:35.143 [peer] sendTransactionsToLocalEngine -> DEBU 55b Sending message CHAIN_TRANSACTION with timestamp seconds:1487799875 nanos:143438691 to local engine vp0_1 | 21:44:35.143 [consensus/noops] RecvMsg -> DEBU 55c Handling Message of type: CHAIN_TRANSACTION vp0_1 | 21:44:35.143 [consensus/noops] broadcastConsensusMsg -> DEBU 55d Broadcasting CONSENSUS vp0_1 | 21:44:35.143 [peer] Broadcast -> DEBU 55e Broadcast took 1.249s vp0_1 | 21:44:35.143 [consensus/noops] RecvMsg -> DEBU 55f Sending to channel tx uuid: 1c1811d0-a958-4c58-ab1d-e1df550c18a3 vp0_1 | 21:44:35.143 [rest] processChaincodeInvokeOrQuery -> INFO 560 Successfully submitted invoke transaction with txid (1c1811d0-a958-4c58-ab1d-e1df550c18a3) vp0_1 | 21:44:35.143 [rest] ProcessChaincode -> INFO 561 REST successfully submitted invoke transaction: {"jsonrpc":"2.0","result":{"status":"OK","message":"1c1811d0-a958-4c58-ab1d-e1df550c18a3"},"id":2} . .
链代码日志输出如下所示: $ ./build/distributions/Example/bin/Example Hello world! starting [Ljava.lang.String;@7ef20235 Feb 22, 2017 3:26:57 PM example.Example main INFO: starting Feb 22, 2017 3:26:57 PM org.hyperledger.java.shim.ChaincodeBase newPeerClientConnection INFO: Inside newPeerCLientConnection Feb 22, 2017 3:26:57 PM io.grpc.internal.TransportSet$1 call INFO: Created transport io.grpc.netty.NettyClientTransport@765e4953(/127.0.0.1:7051) for /127.0.0.1:7051 Feb 22, 2017 3:27:02 PM io.grpc.internal.TransportSet$TransportListener transportReady INFO: Transport io.grpc.netty.NettyClientTransport@765e4953(/127.0.0.1:7051) for /127.0.0.1:7051 is ready Feb 22, 2017 3:27:24 PM example.Example run INFO: In run, function: Feb 22, 2017 3:27:24 PM example.Example run SEVERE: No matching case for function: Feb 22, 2017 3:30:55 PM example.Example run INFO: In run, function:hello hello invoked
我再次给出了所有链代码输出。您可以看到哪些地方( 第 16 行 )调用了 hello 函数。
现在您已知道如何在本地区块链网络上构建、部署和运行 Java 链代码。在下一节中,将会使用 Eclipse IDE(几乎)从头编写一个链代码程序,使用 Gradle 构建该链代码程序,然后使用 SoapUI 体验它。
原文: https://www.ibm.com/developerworks/cn/java/j-chaincode-for-java-developers/index.html
作者: J Steven Perry 如果你希望 高效的 学习以太坊DApp开发,可以访问汇智网提供的 最热门 在线互动教程: 适合区块链新手的以太坊智能合约和DApp实战入门教程 区块链+IPFS+Node.js+MongoDB+Express去中心化以太坊电商应用开发实战
其他更多内容也可以访问 这个以太坊博客 。
区块链
2018-05-23 09:06:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>> pragma solidity ^0.4.20; // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md contract NanToken { //Token //Methods //NOTE: Callers MUST handle false from returns (bool success). Callers MUST NOT assume that false is never returned! // 所有 returns (bool success) 的方法,都要考虑返回false的逻辑; //name //Returns the name of the token - e.g. "MyToken". // //OPTIONAL - This method can be used to improve usability, but interfaces and other contracts MUST NOT expect these values to be present. function name() view returns (string name); //symbol //Returns the symbol of the token.E.g. "HIX". // //OPTIONAL - This method can be used to improve usability, but interfaces and other contracts MUST NOT expect these values to be present. function symbol() view returns (string symbol); //decimals //Returns the number of decimals the token uses - e.g. 8, means to divide the token amount by 100000000 to get its user representation. // //OPTIONAL - This method can be used to improve usability, but interfaces and other contracts MUST NOT expect these values to be present. // 精度 function decimals() view returns (uint8 decimals); //totalSupply //Returns the total token supply. function totalSupply() view returns (uint256 totalSupply); //balanceOf //Returns the account balance of another account with address _owner. // 总量 function balanceOf(address _owner) view returns (uint256 balance); //transfer //Transfers _value amount of tokens to address _to, and MUST fire the Transfer event. The function SHOULD throw if the _from account balance does not have enough tokens to spend. // //Note Transfers of 0 values MUST be treated as normal transfers and fire the Transfer event. // 从当前地址转指定量到指定地址 // 若当前地址没有足够的余额,应该抛出异常 // 每次调用成功,哪怕数量是0,都必须触发 Transfer 事件; function transfer(address _to, uint256 _value) returns (bool success); //transferFrom //Transfers _value amount of tokens from address _from to address _to, and MUST fire the Transfer event. // //The transferFrom method is used for a withdraw workflow, allowing contracts to transfer tokens on your behalf. This can be used for example to allow a contract to transfer tokens on your behalf and / or to charge fees in sub- currencies. The function SHOULD throw unless the _from account has deliberately authorized the sender of the message via some mechanism. // //Note Transfers of 0 values MUST be treated as normal transfers and fire the Transfer event. // 用于提币逻辑; // 每次调用成功必须触发 Transfer 事件;哪怕数量是0; function transferFrom(address _from, address _to, uint256 _value) returns (bool success); //approve //Allows _spender to withdraw from your account multiple times, up to the _value amount. If this function is called again it overwrites the current allowance with _value. // //NOTE : To prevent attack vectors like the one described here[https://docs.google.com/document/d/1YLPtQxZu1UAvO9cZ1O2RPXBbT0mooh4DYKjA_jp-RLM/] and discussed here[https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729], clients SHOULD make sure to create user interfaces in such a way that they set the allowance first to 0 before setting it to another value for the same spender. THOUGH The contract itself shouldn't enforce it, to allow backwards compatibility with contracts deployed before // 允许指定的地址 分一次或多次从当前地址提币;若再次调用此方法,则重置数量 // 为避免攻击,客户端实现时应该先向某地址设置数量为0,再给相同的地址设置数量为 实际的数量; // 这为了向后兼容之前部署的合约,虽然不是强制要求 function approve(address _spender, uint256 _value) returns (bool success); //allowance //Returns the amount which _spender is still allowed to withdraw from _owner. // 查询 owner 授权给 spender 的剩余提币数量 function allowance(address _owner, address _spender) view returns (uint256 remaining); //Events //Transfer //MUST trigger when tokens are transferred, including zero value transfers. // //A token contract which creates new tokens SHOULD trigger a Transfer event with the _from address set to 0x0 when tokens are created. // token 被 成功 transfer 后,需要触发Transfer 事件,哪怕数量为0; // 当创建一个新的token后,应该触发Transfer 事件, event Transfer(address indexed _from, address indexed _to, uint256 _value); //Approval //MUST trigger on any successful call to approve(address _spender, uint256 _value). // 每次approve方法被成功调用后,都必须触发 Approval事件; event Approval(address indexed _owner, address indexed _spender, uint256 _value)}; }
区块链
2018-05-23 00:27:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
本文首发于 深入浅出区块链社区 原文链接: 智能合约语言 Solidity 教程系列10 - 完全理解函数修改器 原文已更新,请读者前往原文阅读
这是Solidity教程系列文章第10篇,带大家完全理解Solidity的函数修改器。 Solidity系列完整的文章列表请查看 分类-Solidity 。
写在前面
Solidity 是以太坊智能合约编程语言,阅读本文前,你应该对以太坊、智能合约有所了解, 如果你还不了解,建议你先看 以太坊是什么
欢迎订阅 区块链技术专栏 阅读更全面的分析文章。
函数修改器(Function Modifiers)
函数修改器(Modifiers)可以用来改变一个函数的行为。比如用于在函数执行前检查某种前置条件。 如果熟悉Python的同学,会发现函数修改器的作用和Python的装饰器很相似。
修改器是一种可被继承合约属性,同时还可被继承的合约重写(override)。下面我们来看一段示例代码: pragma solidity ^0.4.11; contract owned { function owned() public { owner = msg.sender; } address owner; // 定义了一个函数修改器,可被继承 // 修饰时,函数体被插入到 “_;” 处 // 不符合条件时,将抛出异常 modifier onlyOwner { require(msg.sender == owner); _; } } contract mortal is owned { // 使用继承的`onlyOwner` function close() public onlyOwner { selfdestruct(owner); } } contract priced { // 函数修改器可接收参数 modifier costs(uint price) { if (msg.value >= price) { _; } } } contract Register is priced, owned { mapping (address => bool) registeredAddresses; uint price; function Register(uint initialPrice) public { price = initialPrice; } // 需要提供payable 以接受以太 function register() public payable costs(price) { registeredAddresses[msg.sender] = true; } function changePrice(uint _price) public onlyOwner { price = _price; } }
上面onlyOwner就是定义的一个函数修改器,当用这个修改器区修饰一个函数时,则函数必须满足onlyOwner的条件才能运行,这里的条件是:必须是合约的创建这才能调用函数,否则抛出异常。 我们在 实现一个可管理、增发、兑换、冻结等高级功能的代币 文章中就使用了这个函数修改器。
多个修改器
如果同一个函数有多个修改器,他们之间以空格隔开,修饰器会依次检查执行。
在修改器中或函数内的显式的return语句,仅仅跳出当前的修改器或函数。返回的变量会被赋值,但执行流会在前一个修改器后面定义的"_"后继续执行, 如: contract Mutex { bool locked; modifier noReentrancy() { require(!locked); locked = true; _; locked = false; } // 防止递归调用 // return 7 之后,locked = false 依然会执行 function f() public noReentrancy returns (uint) { require(msg.sender.call()); return 7; } }
修改器的参数可以是任意表达式。在此上下文中,所有的函数中引入的符号,在修改器中均可见。但修改器中引入的符号在函数中不可见,因为它们有可能被重写。
深入理解修改器的执行次序
再来看一个复杂一点的例子,来深入理解修改器: pragma solidity ^0.4.11; contract modifysample { uint a = 10; modifier mf1 (uint b) { uint c = b; _; c = a; a = 11; } modifier mf2 () { uint c = a; _; } modifier mf3() { a = 12; return ; _; a = 13; } function test1() mf1(a) mf2 mf3 public { a = 1; } function test2() public constant returns (uint) { return a; } }
上面的智能合约运行test1()之后,状态变量a的值是多少, 是1, 11, 12,还是13呢? 答案是 11, 大家可以运行下test2获取下a值。
我们来分析一下 test1, 它扩展之后是这样的: uint c = b; uint c = a; a = 12; return ; _; a = 13; c = a; a = 11;
这个时候就一目了然了,最后a 为11, 注意第5及第6行是不是执行的。
参考视频
我们也推出了目前市面上最全的视频教程: 深入详解以太坊智能合约语言Solidity 目前我们也在 招募体验师 ,可以点击 链接 了解。
参考文献
官方文档-Function Modifiers
如果你想和认识我,和我建立联系,欢迎加入知识星球 深入浅出区块链 ,我会在星球为大家解答技术问题,作为星友福利,星友可加入我创建的区块链技术群,群内已经聚集了100多位区块链技术爱好者。
☛ 我的知识星球为各位解答区块链技术问题,欢迎加入讨论。 ☛ 关注公众号“深入浅出区块链技术”第一时间获取区块链技术信息,系统学习区块链,打造最好的区块链技术文章。
区块链
2018-05-22 13:03:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
本文首发于 深入浅出区块链社区 原文链接: 智能合约语言 Solidity 教程系列9 - 错误处理 原文已更新,请读者前往原文阅读
这是Solidity教程系列文章第9篇介绍Solidity 错误处理。 Solidity系列完整的文章列表请查看 分类-Solidity 。
写在前面
Solidity 是以太坊智能合约编程语言,阅读本文前,你应该对以太坊、智能合约有所了解, 如果你还不了解,建议你先看 以太坊是什么
欢迎订阅 区块链技术专栏 阅读更全面的分析文章。
什么是错误处理
错误处理是指在程序发生错误时的处理方式,Solidity处理错误和我们常见的语言不一样,Solidity是通过回退状态的方式来处理错误。发生异常时会撤消当前调用(及其所有子调用)所改变的状态,同时给调用者返回一个错误标识。注意 捕捉异常是不可能的 ,因此没有try ... catch...。
为什么Solidity处理错误要这样设计呢? 我们可以把区块链理解为是全球共享的分布式事务性数据库。 全球共享 意味着参与这个网络的每一个人都可以读写其中的记录。如果想修改这个数据库中的内容,就必须创建一个事务, 事务 意味着要做的修改(假如我们想同时修改两个值)只能被完全的应用或者一点都没有进行。 学习过数据库的同学,应该理解事务的含义,如果你对事务一词不是很理解,建议你搜索一下“数据库事务“。 Solidity错误处理就是要保证每次调用都是事务性的。
如何处理
Solidity提供了两个函数assert和require来进行条件检查,如果条件不满足则抛出异常。assert函数通常用来检查(测试)内部错误,而require函数来检查输入变量或合同状态变量是否满足条件以及验证调用外部合约返回值。 另外,如果我们正确使用assert,有一个Solidity分析工具就可以帮我们分析出智能合约中的错误,帮助我们发现合约中有逻辑错误的bug。
除了可以两个函数assert和require来进行条件检查,另外还有两种方式来触发异常: revert 函数可以用来标记错误并回退当前调用 使用 throw 关键字抛出异常(从0.4.13版本,throw关键字已被弃用,将来会被淘汰。)
当子调用中发生异常时,异常会自动向上“冒泡”。 不过也有一些例外:send,和底层的函数调用call, delegatecall,callcode,当发生异常时,这些函数返回false。
注意:在一个不存在的地址上调用底层的函数call,delegatecall,callcode 也会返回成功,所以我们在进行调用时,应该总是优先进行函数存在性检查。
在下面通过一个示例来说明如何使用require来检查输入条件,以及assert用于内部错误检查: pragma solidity ^0.4.0; contract Sharer { function sendHalf(address addr) public payable returns (uint balance) { require(msg.value % 2 == 0); // 仅允许偶数 uint balanceBeforeTransfer = this.balance; addr.transfer(msg.value / 2); // 如果失败,会抛出异常,下面的代码就不是执行 assert(this.balance == balanceBeforeTransfer - msg.value / 2); return this.balance; } }
我们实际运行下,看看异常是如何发生的: 首先打开 Remix ,贴入代码,点击创建合约。如下图: 运行测试1:附加1wei (奇数)去调用sendHalf,这时会发生异常,如下图:
运行测试2:附加2wei 去调用sendHalf,运行正常。 运行测试3:附加2wei以及sendHalf参数为当前合约本身,在转账是发生异常,因为合约无法接收转账,错误提示上图类似。
assert类型异常
在下述场景中自动产生assert类型的异常: 如果越界,或负的序号值访问数组,如i >= x.length 或 i < 0时访问x[i] 如果序号越界,或负的序号值时访问一个定长的bytesN。 被除数为0, 如5/0 或 23 % 0。 对一个二进制移动一个负的值。如:5<require类型异常
在下述场景中自动产生require类型的异常: 调用 throw 如果调用 require 的参数为false 如果你通过消息调用一个函数,但在调用的过程中,并没有正确结束(gas不足,没有匹配到对应的函数,或被调用的函数出现异常)。底层操作如call,send,delegatecall或callcode除外,它们不会抛出异常,但它们会通过返回false来表示失败。 如果在使用new创建一个新合约时出现第3条的原因没有正常完成。 如果调用外部函数调用时,被调用的对象不包含代码。 如果合约没有payable修饰符的public的函数在接收以太币时(包括构造函数,和回退函数)。 如果合约通过一个public的getter函数(public getter funciton)接收以太币。 如果**.transfer()**执行失败
当发生require类型的异常时,Solidity会执行一个回退操作(指令0xfd)。 当发生assert类型的异常时,Solidity会执行一个无效操作(指令0xfe)。 在上述的两种情况下,EVM都会撤回所有的状态改变。是因为期望的结果没有发生,就没法继续安全执行。必须保证交易的原子性(一致性,要么全部执行,要么一点改变都没有,不能只改变一部分),所以需要撤销所有操作,让整个交易没有任何影响。
注意assert类型的异常会消耗掉所有的gas, 而require从大都会版本(Metropolis, 即目前主网所在的版本)起不会消耗gas。
参考视频
我们也推出了目前市面上最全的视频教程: 深入详解以太坊智能合约语言Solidity 目前我们也在 招募课程体验师 ,可以点击 链接 了解。
参考文献 Solidity 错误处理
☛ 我的知识星球为各位解答区块链技术问题,欢迎加入讨论。 ☛ 关注公众号“深入浅出区块链技术”第一时间获取区块链技术信息,系统学习区块链,打造最好的区块链技术文章。
区块链
2018-05-22 13:02:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
本文首发于 深入浅出区块链社区 原文链接: 剖析非同质化代币ERC721-全面解析ERC721标准 原文已更新,请读者前往原文阅读
什么是ERC-721?现在我们看到的各种加密猫猫狗狗都是基于ERC-721创造出来的,每只都是一个独一无二的ERC-721代币,不过ERC-721在区块链世界远不止猫猫狗狗,它更大的想象空间在于将物理世界的资产映射到区块链上。本文就来剖析下什么是ERC721.
ERC721是什么
在 创建代币 一篇,我们讲到过ERC20代币, 和ERC20一样,ERC721同样是一个代币标准,ERC721官方简要解释是Non-Fungible Tokens,简写为NFTs,多翻译为非同质代币。 ERC721 是由Dieter Shirley 在2017年9月提出。Dieter Shirley 正是谜恋猫CryptoKitties背后的公司Axiom Zen的技术总监。因此谜恋猫也是第一个实现了ERC721 标准的去中心化应用。ERC721号提议已经被以太坊作为标准接受,但该标准仍处于草稿阶段。本文介绍的ERC721标准基于最新(2018/03/23官方提议。
那怎么理解 非同质 代币呢?
非同质代表独一无二,谜恋猫为例,每只猫都被赋予拥有基因,是独一无二的(一只猫就是一个NFTs),猫之间是不能置换的。这种独特性使得某些稀有猫具有收藏价值,也因此受到追捧。
ERC20代币是可置换的,且可细分为N份(1 = 10 * 0.1), 而ERC721的Token最小的单位为1,无法再分割。 如果同一个集合的两个物品具有不同的特征,这两个物品是非同质的,而同质是某个部分或数量可以被另一个同等部分或数量所代替。
非同质性其实广泛存在于我们的生活中,如图书馆的每一本,宠物商店的每一只宠物,歌手所演唱的歌曲,花店里不同的花等等,因此ERC721合约必定有广泛的应用场景。通过这样一个标准,也可建立跨功能的NFTs管理和销售平台(就像有支持ERC20的交易所和钱包一样),使生态更加强大。
ERC721标准
ERC721最为一个合约标准,提供了在实现ERC721代币时必须要遵守的协议,要求每个ERC721标准合约需要实现ERC721及ERC165接口,接口定义如下: pragma solidity ^0.4.20; interface ERC721 /* is ERC165 */ { event Transfer(address indexed _from, address indexed _to, uint256 _tokenId); event Approval(address indexed _owner, address indexed _approved, uint256 _tokenId); event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved); function balanceOf(address _owner) external view returns (uint256); function ownerOf(uint256 _tokenId) external view returns (address); function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external payable; function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable; function transferFrom(address _from, address _to, uint256 _tokenId) external payable; function approve(address _approved, uint256 _tokenId) external payable; function setApprovalForAll(address _operator, bool _approved) external; function getApproved(uint256 _tokenId) external view returns (address); function isApprovedForAll(address _owner, address _operator) external view returns (bool); }
接口说明: balanceOf(): 返回由_owner 持有的NFTs的数量。 ownerOf(): 返回tokenId代币持有者的地址。 approve(): 授予地址_to具有_tokenId的控制权,方法成功后需触发Approval 事件。 setApprovalForAll(): 授予地址_operator具有所有NFTs的控制权,成功后需触发ApprovalForAll事件。 getApproved()、isApprovedForAll(): 用来查询授权。 safeTransferFrom(): 转移NFT所有权,一次成功的转移操作必须发起 Transer 事件。函数的实现需要做一下几种检查: 调用者msg.sender应该是当前tokenId的所有者或被授权的地址 _from 必须是 _tokenId的所有者 _tokenId 应该是当前合约正在监测的NFTs 中的任何一个 _to 地址不应该为 0 如果_to 是一个合约应该调用其onERC721Received方法, 并且检查其返回值,如果返回值不为 bytes4(keccak256("onERC721Received(address,uint256,bytes)")) 抛出异常。 一个可接收NFT的合约必须实现ERC721TokenReceiver接口: interface ERC721TokenReceiver { /// @return `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))` function onERC721Received(address _from, uint256 _tokenId, bytes data) external returns(bytes4); } transferFrom(): 用来转移NFTs, 方法成功后需触发Transfer事件。调用者自己确认_to地址能正常接收NFT,否则将丢失此NFT。此函数实现时需要检查上面条件的前4条。
ERC165 标准
ERC721标准同时要求必须符合ERC165标准 ,其接口如下: interface ERC165 { function supportsInterface(bytes4 interfaceID) external view returns (bool); }
ERC165 同样是一个合约标准,这个标准要求合约提供其实现了哪些接口,这样再与合约进行交互的时候可以先调用此接口进行查询。 interfaceID为函数选择器,计算方式有两种,如: bytes4(keccak256('supportsInterface(bytes4)')); 或 ERC165.supportsInterface.selector ,多个函数的接口ID为函数选择器的异或值。 关于ERC165,这里不深入介绍,有兴趣的同学可以阅读 官方提案 。
可选实现接口:ERC721Metadata
ERC721Metadata 接口用于提供合约的元数据:name , symbol 及 URI(NFT所对应的资源)。 其接口定义如下: interface ERC721Metadata /* is ERC721 */ { function name() external pure returns (string _name); function symbol() external pure returns (string _symbol); function tokenURI(uint256 _tokenId) external view returns (string); }
接口说明: name(): 返回合约名字,尽管是可选,但强烈建议实现,即便是返回空字符串。 symbol(): 返回合约代币符号,尽管是可选,但强烈建议实现,即便是返回空字符串。 tokenURI(): 返回_tokenId所对应的外部资源文件的URI(通常是IPFS或HTTP(S)路径)。外部资源文件需要包含名字、描述、图片,其格式的要求如下: { "title": "Asset Metadata", "type": "object", "properties": { "name": { "type": "string", "description": "Identifies the asset to which this NFT represents", }, "description": { "type": "string", "description": "Describes the asset to which this NFT represents", }, "image": { "type": "string", "description": "A URI pointing to a resource with mime type image/* representing the asset to which this NFT represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive.", } } }
tokenURI通常是被web3调用,以便在应用层做相应的查询和展示。
可选实现接口:ERC721Enumerable
ERC721Enumerable的主要目的是提高合约中NTF的可访问性,其接口定义如下: interface ERC721Enumerable /* is ERC721 */ { function totalSupply() external view returns (uint256); function tokenByIndex(uint256 _index) external view returns (uint256); function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256); }
接口说明: totalSupply(): 返回NFT总量 tokenByIndex(): 通过索引返回对应的tokenId。 tokenOfOwnerByIndex(): 所有者可以一次拥有多个的NFT, 此函数返回_owner拥有的NFT列表中对应索引的tokenId。
补充说明
NTF IDs
NTF ID,即tokenId,在合约中用唯一的uint265进行标识,每个NFT的ID在智能合约的生命周期内不允许改变。推荐的实现方式有: 从0开始,每新加一个NFT,NTF ID加1 使用sha3后uuid 转换为 NTF ID
与ERC-20的兼容性
ERC721标准尽可能遵循 ERC-20 的语义,但由于同质代币与非同质代币之间的根本差异,并不能完全兼容ERC-20。
交易、挖矿、销毁
在实现transter相关接口时除了满足上面的的条件外,我们可以根据需要添加自己的逻辑,如加入黑名单等。 同时挖矿、销毁尽管不是标准的一部分,我们可以根据需要实现。
参考实现
参考实现为订阅用户专有福利,请订阅我的小专栏: 区块链技术 查看。

参考文献 EIPS-165 EIPS-721
☛ 我的知识星球为各位解答区块链技术问题,欢迎加入讨论。 ☛ 关注公众号“深入浅出区块链技术”第一时间获取区块链技术信息,系统学习区块链,打造最好的区块链技术文章。
区块链
2018-05-22 13:00:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
DAO Attack
https://etherscan.io/token/TheDAO#readContract

Pariity Hack
https://blog.zeppelin.solutions/on-the-parity-wallet-multisig-hack-405a8c12e8f7
https://medium.com/@Pr0Ger/another-parity-wallet-hack-explained-847ca46a2e1c
https://paritytech.io/the-multi-sig-hack-a-postmortem/
360
http://blogs.360.cn/blog/eos-node-remote-code-execution-vulnerability/

RMC/UET代币合约
https://mp.weixin.qq.com/s/qDTrZPy5f4_-V2F4DpzoNA

https://paper.seebug.org/612/
http://blockchain.unica.it/projects/ethereum-survey/index.html
http://cryptodefense.io/
Reentrancy : Do not perform external calls in contracts. If you do, ensure that they are the very last thing you do. Send can fail : When sending money, your code should always be prepared for the send function to fail. Loops can trigger gas limit : Be careful when looping over state variables, which can grow in size and make gas consumption hit the limits. Call stack depth limit : Don’t use recursion, and be aware that any call can fail if stack depth limit is reached. EDIT : this is no longer a problem . Timestamp dependency : Do not use timestamps in critical parts of the code, because miners can manipulate them.

币安等交易的ERC20币种存隐患 可人为操纵币价套利
2018.06.11 17:20:24Bianews
Bianews 6月11日消息,区块链安全公司PeckShield今日发布报告称:多个已经在主流交易所上线的ERC20币种的智能合约代码存在严重的安全隐患,“攻击者”可通过公开的接口,以“零成本”技术手段实施割韭菜套利行为。
PeckShield调查发现,目前已知有700多个ERC20币种存在此类问题。已经证实了至少有数十个币种已经在包括币安、火币以及OKex在内的主流交易所公开上线交易,且交易量巨大。其中最大币种市值已达1.5亿美金,全部币种共影响波及数十万投资者。
PeckShield已向包括火币、币安以及OKex等多个主流交易所发出安全警报。
PeckShield研究大量智能合约代码发现,攻击者可使用如下两种技术手段来操纵币价:
安全问题一:项目owner可无限增发Token
存在问题的ERC20币种智能合约有一个仅owner可调用的方法:mintToken,这个可被 owner用于增发token。
通常一个项目在上交易所之前即预售期,增发行为尚算合理,项 目方定向空投一些Token给特定地址,目的是为了激励社区用户参与活跃度。但在交易所上线可正常交易后,此种借助智能合约的增发行为会让项目owner空手套利,会严重影响市场平衡。
(图一:受影响智能合约存在的mintToken问题)
目前发现有10余种存在此类问题的可交易Token,他们存在于23个包括 Binance和OKex这样的顶级交易所,且目前交易量巨大,一旦被利用可以影响数以万计的 投资者。
以下为披露此信息时,已经发现的10个存在此问题的Token。

安全问题二:可操纵的价格和不公平的套利行为
存在问题的ERC20币种的智能合约有三个可调用方法:
1) setPrices: 仅owner可访问,用来调整通过方法buy以及sell进行的token的买卖价格 (即buyPrice / sellPrice);
2) buy: 公开且任意可访问方法,根据buyPrice购买token;
3) sell: 公开且任意可访问方法,根据sellPrice购买token。 为描述方便起见,将buyPrice / sellPrice称之为owner可操纵价格,并将token在 交易所的价格称为市场价格。
(图二:可操纵和利用的智能合约接口)
按理说,一个币种上交易所后,交易走量都需要通过交易平台,成交时的买卖价格也是和市 场保持同步的。然而,在图二代码中发现,项目owner可以通过智能合约任意修改买 入价和卖出价,完全不需要依照市场价格。这样以来“套利”空间就有了,套利者可以在 Token市场价格略高通过接口定一个较低的买入价,然后再以市场价格卖出,套利者还可以用市场价格买入Token,再设定一个比市场价格高的价格卖出。
不管怎样,这是一种干涉市场对流通Token“定价权”的行为,严重点讲已经控制了市场,对市场上其他投资者 而言存在极大的不公平。
以下为披露信息时,已经发现的9个存在此问题的Token。

截至目前为止,已发现9个可交易的token,在26个交易所上线交易。其中如SUB、INT 和SWFTC等token都在主流的交易所上线并拥有巨大的交易量和影响力。
其它安全问题
进一步研究发现,如图三和图四,sell或buy方法中存在整数溢出漏洞,项目owner 在布局第二种套利行为的时候,可以设计一个套利陷阱,owner能够利用该漏洞损害普通用户应得的收益。
(图三:受影响的买方智能合约类别)
(图四:受影响的卖方智能合约类别)
通常来讲,传统股票证券市场存在这样的“割韭菜”套路,幕后大庄通过周期性低拉高抛来 制造市场震荡来收割韭菜,利用的是不少散户投资者盲目追涨杀跌的心理。大多数情况下, 数字货币市场的大部分割韭菜行为也是基于此市场化操盘来实现。最新发现的此种借助智能合约漏洞割韭菜的方式,不经过市场,以技术手段进行零成本收割,对数字货币市场的稳定性威胁极大。
众所周知,交易所控着着数字货币资产的流进和流出,作为一个数字资产中转枢纽,交易所自诞生以来漏洞和安全事件就层出不穷,数年来,围绕交易所出现的黑客攻击事件,已造成超百亿美元的损失。
然而,这仅仅是明面上技术漏洞诱发的黑客攻击事件,幕后还有借助智能合约代码漏洞实施操纵币价展开不公平套利行为。
6月9日,PeckShield发现了上述安全隐患,在评估了安全威胁之后第一时间通知了相 关交易所,希望携手交易所来共同预防危机的发生。不少交易所(如币安)和项目方(如 Substratum,即SUB)在得到通报后已积极做出了响应。
https://tech.sina.cn/i/gn/2018-06-11/detail-ihcufqih0816780.d.html?cre=tianyi&mod=wtech&loc=1&r=25&doct=0&rfunc=10&tj=none&tr=25&vt=4&pos=18

区块链
2018-05-29 16:06:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
以太坊是一个分布式的计算平台。它会生成一个名为Ether的加密货币。程序员可以在以太坊区块链上写下“智能合约”,这些以太坊智能合约会根据代码自动执行。
以太坊是什么?
以太坊经常与比特币相提并论,但情况却有所不同。比特币是一种加密货币和分布式支付网络,允许比特币在用户之间转移。 相关: 什么是比特币?它是如何工作的?
以太坊项目有更大的目标。正如Ethereum网站所说,“以太坊是一个运行智能合约的分布式平台”。这些智能合约运行在“以太坊虚拟机”上,这是一个由所有运行以太网节点的设备组成的分布式计算网络。
“分布式平台”部分意味着任何人都可以建立并运行以太坊节点,就像任何人都可以运行比特币节点一样。任何想要在节点上运行“智能合约”的人都必须向Ether中的这些节点的运营商付款,这是一个与以太坊相关的加密货币。因此,运行以太网节点的人提供计算能力,并在以太网中获得支付,这与运行比特币节点的人提供哈希能力并以比特币支付的方式类似。
换句话说,虽然比特币仅仅是一个区块链和支付网络,但以太坊是一个分布式计算网络,其区块链可以用于许多其他事情。 以太坊白皮书 中提供了详细信息。
以太是什么?
以太网是与以太坊区块链相关的数字标记(或者说就是加密货币)。换句话说,以太是代币,以太坊是平台。但是,现在人们经常交替使用这些术语。例如,Coinbase允许你购买以太坊代币(Ethereum),即代表以太币代币。
这在技术上就是“ altcoin ”,这实际上意味着一个非比特币加密货币。和比特币一样,Ether也受到分布式区块链支持 - 在这种情况下是以太坊区块链。
想要在以太坊区块链上创建应用程序或 以太坊 智能合约 的开发人员需要以太网代币来支付节点来托管它,而基于以太坊的应用程序的用户可能需要以太网来支付这些应用程序中的服务费用。人们也可以在以太坊网络之外销售服务,并接受以太网支付,或者可以在交易所以现金形式出售以太币代币 - 就像比特币一样。
为什么分布式应用程序有趣?
比特币区块链存储比特币交易的历史,就是这样。以太坊区块链将以太币代币存储在人们的钱包中,但它还存储每个智能合约的最新状态以及每个智能合约的代码。
区块链是存储在多个位置的分布式账本,所以这意味着智能合约数据由那些以太坊节点存储。如果您在区块链上创建“智能合约”(也称为应用程序),则会以分布式的方式进行存储和运行。
为了比较,请考虑我们今天使用的许多应用程序。这包括Gmail等电子邮件应用程序,Microsoft OneNote等笔记记录应用程序,以及使用应用程序并将数据存储在公司服务器上的任何其他应用程序。如果存储数据的公司禁止您的帐户,关闭应用程序或停业,那么除非您有脱机备份副本,否则您将丢失该应用程序中的所有数据。
如果您使用的是构建在以太坊之上的应用程序,组成应用程序的代码(智能合约代码)和个人数据(智能合约的状态)将存储在区块链中。每当您使用应用程序并更改数据时,所有以太坊节点都会更新智能合约的状态。这意味着没有中央“失败点”可能会阻止您访问数据或关闭您使用的应用程序。您的数据和应用程序的代码本身将在全球范围内备份,并且没有人可以将所有这些备忘录脱机。当然,您的数据将通过区块链进行加密,所以没有其他人可以读取它。
什么是智能合约?
智能合约是在以太坊虚拟机上运行的应用程序。这是一个分布的“世界计算机”,计算能力由所有以太坊节点提供。提供计算能力的任何节点都将以Ether数字货币作为资源支付。
他们被命名为智能合约,因为您可以编写满足要求时自动执行的“合同”。
例如,想象一下在以太坊之上建立一个类似Kickstarter的众筹服务。有人可以建立一个 以太坊智能合约 ,将资金汇集到别人身上。这个智能合约可以写成这样的话:当将100,000美元的货币添加到池中时,它将全部发送给收件人。或者,如果一个月内没有达到100,000美元的门槛,所有的货币都将被发回给货币的原始持有人。当然,这将使用以太币代替美元。
这一切都将根据智能合同代码进行,智能合同代码可自动执行交易,而无需可信任的第三方持有货币并签署交易。例如,Kickstarter在5%的付款处理费之上收取5%的费用,这意味着在$ 100,000的众筹项目中将收取8000到10000美元的费用。智能合约不需要向像Kickstarter这样的第三方支付费用。
智能合约可以用于许多不同的事情。开发人员可以创建智能合约,为其他智能合约提供功能,类似于软件库的工作方式。或者,智能合约可以简单地用作应用程序来存储以太坊区块链上的信息。
为了真正执行智能合同代码,有人必须发送足够的以太网代币作为交易费 - 多少取决于所需的计算资源。这为以太坊节点参与并提供计算能力付出了代价。
CryptoKitties使用智能合约
在以太坊网络上使用智能合约构建的最知名的应用之一是CryptoKitties,它自称是“世界上第一款基于区块链技术构建的游戏”。
从本质上讲,CryptoKitties是存储在以太坊区块链中的一种数字“可收集”形式。 CryptoKitties提供了在Ethereum网络上存储和交换数字项目的能力的良好演示。
新的CryptoKitties是通过“繁殖”生成的。这涉及到选择两个基本的CryptoKitties并花费以太币代币运行智能合约。合约使用两只选择的猫来产生新的CryptoKitty。这些小猫和繁殖过程的细节存储在以太坊区块链的公共账本上。
您可以“拥有”CryptoKitties,它们存储在以太坊区块链分类账中。您可以将其出售或交易给其他人,也可以购买。这与使用允许您购买,交易和养殖猫的智能手机应用程序不同。这些通常会存储在应用程序自己的服务器上,如果公司关闭应用程序或禁止您的帐户,则可能会丢失珍贵的数字宠物。但是,因为CryptoKitties存储在区块链中,所以不会发生。没有人能把你的小猫带走。
2017年12月 - 巧合的是,在比特币的历史最高价格附近,人们花费了超过1200万美元的CryptoKitties的Ether费用,而最昂贵的CryptoKitty售价约为12万美元。
像以太网,比特币和昂贵的绘画一样,CryptoKitties值得人们准备为它们付钱。
原文:howtogeek.com/350322/what-is-ethereum-and-what-are-smart-contracts 作者: Chris Hoffman
区块链
2018-05-29 10:19:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
Ubuntu 14.04 下,Ontology 开发环境构建 、部署及测试
作者:
原文链接: https://my.oschina.net/uchihamadara/blog/1790608
Ubuntu 14.04 下,在 IDEA 中构建 Ontology JAVA SDK 开发环境
作者:
原文链接: https://my.oschina.net/uchihamadara/blog/1798979
Ubuntu 14.04 下,Ontology 区块链浏览器开发
作者:
原文链接: https://my.oschina.net/uchihamadara/blog/1813612
区块链
2018-05-28 20:01:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
作者:知乎用户
链接:https://www.zhihu.com/question/37290469/answer/293890531
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

友情提醒 :比特币采用区块链技术,但是区块链并不等同于比特币;全篇基于比特币底层区块链技术讲述,所以,部分模型可能不适用于以太坊等。另外,由于文章采用了一定的抽象、类举的叙事方式,中间或多或少有些地方会跟区块链底层严谨的技术实现有出入,如果让你觉得困惑,可以在评论下方留言或者私信我一起探讨。最后,也是受限于自己知识结构的不完整,这篇文章会随着我对区块链更深入认识后,随时进行修订,最后更新时间可参考该回答下方的时间戳。

另外,作为一篇科普性文章,大家可以随意转载,注明这篇文章的出处和作者即可,无需再单独私信询问。

---

首先不要把区块链想的过于高深,他是一个分布在全球各地、能够协同运转的数据库存储系统,区别于传统数据库运作——读写权限掌握在一个公司或者一个集权手上(中心化的特征),区块链认为,任何有能力架设服务器的人都可以参与其中。来自全球各地的掘金者在当地部署了自己的服务器,并连接到区块链网络中,成为这个分布式数据库存储系统中的一个节点;一旦加入,该节点享有同其他所有节点完全一样的权利与义务(去中心化、分布式的特征)。与此同时,对于在区块链上开展服务的人,可以往这个系统中的任意的节点进行读写操作,最后全世界所有节点会根据某种机制的完成一次又依次的同步,从而实现在区块链网络中所有节点的数据完全一致。
上图中,高亮的点就是区块链系统中分布在全球各地的一个个节点;而这些节点可以简单理解为一台服务器服务器集群
# 问题的由来
我们反复提到区块链是一个去中心化的系统,确实,「去中心化」在区块链世界里面是一个很重要的概念,很多模型(比如账本的维护、货币的发行、时间戳的设计、网络的维护、节点间的竞争等等等等)的设计都依赖于这个中心思想,那到底什么是去中心化呢?在解释真正去中心化之前,我们还是先简单了解下什么是中心化吧。

中心化?

回忆一下你在网上购买一本书的流程: 第一步,你下单并把钱打给 支付宝 ; 第二步, 支付宝 收款后通知卖家可以发货了; 第三步,卖家收到 支付宝 通知之后给你发货; 第四步,你收到书之后,觉得满意,在 支付宝 上选择确认收货; 第五步, 支付宝 收到通知,把款项打给卖家。流程结束。

你会发现,虽然你是在跟卖家做交易,但是,所有的关键流程都是在跟支付宝打交道。这样的好处在于:万一哪个环节出问题,卖家和买家都可以通过支付宝寻求帮助,让支付宝做出仲裁。这就是一个最简单的基于中心化思维构建的交易模型,它的价值显著,就是建立权威,通过权威背书来获得多方的信任,同时依赖权威方背后的资本和技术实力确保数据的可靠安全。

你一定会摆出一个巨大的问号脸 ⊙.⊙?——“通过权威背书来获得多方的信任,同时依赖权威方背后的资本和技术实力确保数据的可靠安全”,真的可以嘛?!

假如说,支付宝程序发生重大BUG,导致一段时间内的转账记录全部丢失,或者更彻底一点,支付宝的服务器被ISIS恐怖组织的一个导弹全部炸毁了。而我刚刚转出去的100元找谁说理去,这个时候,你就成了刀殂上的鱼肉;支付宝有良心,会勉为其难承认你刚刚转账的事实,但他不承认你也没辙,因为确实连他自己也不知道这笔转账是否真实存在。

上述就是中心化最大的弊端——过分依赖中心和权威,也就意味着逐渐丧失自己的话语权。

去中心化?

那么去中心化的形态是什么样子呢?还是拿刚才那个例子继续,我们构建一个极简的去中心化的交易系统,看看我们是如何在网络上从不认识的卖家手里买到一本书的。 第一步,你下单并把钱打给卖家; 第二步,你将这条转账信息记录在自己账本上; 第三步,你将这条转账信息广播出去; 第四步,卖家和支付宝在收到你的转账信息之后,在他们自己的账本上分别记录; 第五步,卖家发货,同时将发货的事实记录在自己的账本上; 第六步,卖家把这条事实记录广播出去; 第七步,你和支付宝收到这条事实记录,在自己的账本上分别记录; 第八步,你收到书籍。至此,交易流程走完。

刚才“人为刀俎我为鱼肉”的情况在这个体系下就比较难发生,因为所有人的账本上都有着完全一样的交易记录,支付宝的账本服务器坏了,对不起卖家的账本还存在,我的账本还存在;这些都是这笔交易真实发生的铁证。

当然,在这套极简的交易系统中,你已经发现了诸多漏洞和不理解,比如说三方当中有一个是坏人,他故意记录了对他更有利的转账信息怎么办;又比如说消息在传递过程中被黑客篡改了怎么办等等等等。这在以往的计算机概论或者计算机网络书本上中可能都有提及到——“类两军”和“拜占庭将军”问题。这里就不打算赘述,因为暂时跟主线不相关,感兴趣的同学可以去Google或者百度一下,你只需要知道,在我们下面即将展开讲到的区块链系统中,通过巧妙的设计,足以解决上述存在的BUG。

既然话已说到这份上,相信了解一点技术、特别是有运维背景的同学大概能够从极简交易系统中窥视到了更多区块链的一些影子—— 分布式存储,通过多地备份,制造数据冗余 让所有人都有能力都去维护共同一份数据库 让所有人都有能力彼此监督维护数据库的行为

在我看来,你猜测的基本上没错。其实这些就是区块链技术最核心的东西,外人看起来高大上、深不可测,但探究其根本发现就是这么简单和淳朴。当然,这里面肯定会有很多很多很多细枝末节的技术需要重构。

如果你差不多认同上面的观点,那我们应该基本上可以达成共识,分布式部署肯定是构建去中心化网络理所当然的解决方向——通过P2P协议将全世界所有节点计算机彼此相互连接,形成一张密密麻麻的网络;以巧妙的机制,通过节点之间的交易数据同步来保证全球计算机节点的数据共享和一致。

哈哈,说的轻巧,“交易数据这么重要的东西,在一个完全不信任的P2P网络节点中以一种错综复杂的方式传递,数据的一致性和安全性谁来保证,如果说互相监督,他们到底怎么做到?”

好了,不卖关子了,下面让我们围绕这个最最最最直接的问题开始进入到真正区块链的世界,抽丝剥茧看看它到底是如何一步一步形成的,又是如何一步一步稳定运转。

# 从全球节点到交易数据
这张图的制作的意义为的是帮助你在宏观上先快速理解区块链中所涉及到的相关名词以及他们的层级关系。同时,文章的知识结构和设计思路也大抵上也会按照: 首先,将区块作为最小单位体,讲述极简区块链系统是如何运转的; 接着,进入到比区块更小单位体——交易记录,理解区块链是如何处理数据的; 最后,将所有知识点柔和在一起,重回到区块和区块链,完整讲述整个工作流程。

希望你在这个引导和结构下有一个比较好的阅读体验。Let's go~

# 区块,混沌世界的起源

既然已经达成共识,所以,我们事先构建好了一个去中心化的P2P网络;同时,为了让读者朋友们听起来更轻松,我先粗暴的规定在这个极简的区块链系统里,每十分钟有且仅产生一笔交易。

故事继续,在节点的视野里,大概每十分钟会凭空产生一个建立在自己平行宇宙世界的神奇区块(你可以将区块想象为一个盒子),这个区块里放着一些数字货币以及一张小纸条,小纸条上记录了这十分钟内产生的那唯一一笔交易信息,比如说——“小A转账给了小B100元”;当然,这段信息肯定是被加密处理过的,为的就是保证只有小A和小B(通过他们手上的钥匙)才有能力解读里面真正的内容。

这个神奇的区块被创造出来之后,很快被埋在了地底下,至于埋在哪里?没有一个人不知道,需要所有计算机节点一起参与进来掘地三尺后才有可能找到(找到一个有效的工作量证明)。显然,这是一件工作量巨大、成果随机的事件。但是呢,对于计算机节点来说,一旦从地底下挖出这个区块,他将获得区块内价值不菲的数字货币,以及“小A转账给了小B100元”过程中小A所支付的小费。同时,对于这个节点来说,也只有他才有权利真正记录小纸条里的内容,这是一份荣耀,而其他节点相当于只能使用它的复制品,一个已经没有数字货币加持的副本。当然这个神奇的区块还有一些其他很特别的地方,后面我们会再细细聊。

为了更好的描述,我们将计算机节点从地底下挖出区块的过程叫做「挖矿」,刚才说了,这是一件工作量巨大、运气成分较多、但收益丰厚的事儿。

过了一会儿,来自中国上海浦东新区张衡路上的一个节点突然跳出来很兴奋的说:“ 我挖到区块了!里面的小纸条都是有效的!奖励归我!” 。虽然此刻张衡路节点已经拿到了数字货币,但对于其他计算机节点来说,因为这里面还涉及到其他一些利益瓜葛,他们不会选择默认相信张衡路节点所说的话;基于陌生节点彼此不信任的原则,他们拿过张衡路节点所谓挖到的区块(副本),开始校验区块内的小纸条信息是否真实有效等等。在区块链世界里,节点们正是通过校验小纸条信息的准确性,或间接或直接判断成功挖出区块的节点是否撒谎。(如何定义小纸条信息真实有效,后面会讲解,这里暂不做赘述)。

在校验过程中,各个节点们会直接通过下面两个行为表达自己对张衡路节点的认同(准确无误)和态度: 停止已经进行了一半甚至99.99%的挖矿进程; 将张衡路节点成功挖出的区块(副本)追加到自己区块链的末尾。

你可以稍微有点困惑:停止可能已经执行了99.99%的挖矿行为,那之前99.99%的工作不是就白做了嘛?!然后,区块链的末尾又是个什么鬼东西?

对于第一个困惑。我想说,你说的一点没错,但是没办法,现实就是这么残酷,即便工作做了99.99%,那也得放弃,这99.99%的工作劳苦几乎可以视为无用功,绝对的伤财劳众。第二个困惑,区块链和区块链的末尾是什么鬼?这里因为事先并没有讲清楚,但是你可以简单想象一下:区块是周期性不断的产生和不断的被挖出来,一个计算机节点可能事先已经执行了N次“从别人手上拿过区块 -> 校验小纸条有效性”的流程,肯定在自己的节点上早已经存放了N个区块,这些区块会按照时间顺序整齐的一字排列成为一个链状。没错,这个链条,就是你一直以来认为的那个区块链。如果你还是不能够理解,没关系,文章后面还会有很多次机会深入研究。

# 走进区块内,探索消息的本质

上面我们构建了一个最简单的区块链世界的模型,相信大多数同学都已经轻松掌握了。但是别骄傲也别着急,这还只是一些皮毛中的皮毛,坐好,下面我们准备开车了。

前面我们说到“大概每十分钟会凭空产生一个神奇的区块,这个区块里放了一张小纸条,上面记录了这十分钟内产生的这唯一一笔交易信息”。显然,十分钟内产生的交易肯定远不止一条,可能是上万条,这上万条数据在区块链世界是如何组织和处理的呢?另外,为什么在纸条上记录的只是某一次的交易信息,而不是某一个人的余额?余额好像更符合我们现实世界的理解才对。

既然存在这样那样的疑问。现在我们就把视线暂时从“区块”、“区块链”这些看起来似乎较大实体的物质中移开,进入到区块内更微观的世界里一探究竟,看看小纸条到底是怎么一回事,它的产生以及它终其一生的使命: 发起交易的时候,发起人会收到一张小纸条,他需要将交易记录比如说“盗盗转账给张三40元”写在纸上。说来也神奇,当写完的那一刹那,在小纸条的背面会自动将这段交易记录格式化成至少包含了“输入值”和“输出值”这两个重要字段;“输入值”用于记录数字货币的有效来源,“输出值”记录着数字货币发往的对象。 刚刚创建的小纸条立马被标记成为“ 未确认 ”的小纸条。从地下成功挖出区块并最终连接到区块链里的小纸条一开始会被标记为“ 有效 ”。若这条有效的小纸条作为其他交易的输入值被使用,那么,这个有效的小纸条很快会被标记为“ 无效 ”。因为各种原因,区块从链上断开、丢弃,曾经这个区块内被标记为“有效”的小纸条会被重新标记为“未确认”。 区块链里面没有账户余额的概念,你真正拥有的数字资产实际上是一段交易信息;通过简单的加减法运算获知你数字钱包里的余额。

上面的1、2、3仅仅作为结论一开始强行灌输给你的知识点,其中有几个描述可能会有点绕,让你觉得云里雾里,没有关系,因为我们立刻、马上就开始会细说里面的细枝末节。

上图,是区块内,盗盗在一张小纸条上记录下的交易信息,后被格式化的呈现

上图就是从无数打包进区块内的小纸条中,抽取出来的一张,以及它最终被格式化后的缩影。单看右侧的图可能很容易产生误会,虽然看起来有多行,但实际上就是“盗盗转账给张三40个比特币”这一条交易数据另外的一种呈现形态。因为区块链世界里面这么规定,每一条交易记录,必须有能力追溯到交易发起者 发起这笔交易、其中所涉及金额的上一笔全部交易信息;即这笔钱从何而来的问题。这其实很容易理解,在去中心化的网络中,通过建立交易链、和通过交易链上的可溯源性间接保证数据安全和有效。

我们继续看,在区块链世界里,我们是如何仅通过“盗盗转账给张三40个比特币” 这条交易信息完成转账流程的。其实跟现实中你在路边买一个包子的流程大抵上相同。

第一步:判断是否有足够的余额完成交易
这里我们再一次重申,在比特币的区块链世界里是没有余额的概念(以太坊的底层区块链有余额概念),余额是通过简单数字的加减最终获得,你拥有所谓的数字货币实际上是因为你拥一条交易记录,即 “盗盗转账给张三40个比特币”!这里,我们还是拿这条记录说事:

追溯“输出值”是“盗盗”相关的 全部有效交易记录 作为,对有效交易中的数字进行简单求和,判断是否大于等于40,如果确实大于等于,则将这些有效的交易记录合并形成一条新的交易记录(如下图)。如果小于40,其实可以不需要再继续往下探讨。

就上图的例子,我们追溯到曾经转账给盗盗的 有效交易记录 有“小A转账给盗盗10 btc”、“小B转账给盗盗20 btc”、“小C转账给盗盗 25 btc”,我们需要将这三条交易记录合并成一条更复杂描述的交易记录,即 “( 小A转账给盗盗10 btc + 小B转账给盗盗20 btc + 小C转账给盗盗 25 btc ) 转账给张三40 btc ”

第二步:判断是否需要找零
对追溯到的有效交易数字求和,如果发现大于需要支付的金额,需要将多出的数字重新支付给自己,相当于找零。对应生成了一条全新的交易记录(如下图)。

就上图例子来说,我们最后合并成的交易记录 “( 小A转账给盗盗10 btc + 小B转账给盗盗20 btc + 小C转账给盗盗 25 btc + 盗盗转账给盗盗15 btc ) 转账给张三40 btc ” 事实上等同于“盗盗转账给张三40 btc”。其中“盗盗转账给盗盗15 btc”就可以理解找零。

第三步:发出去,让全球节点认同和备份小纸条
这条内部重新处理过的复杂交易记录被塞进区块,埋到地下,等待节点挖出来,一旦区块被挖矿成功,并且该区块最终被连在了区块链的主链上。张三将最终拥有了这条交易记录,而先前的“小A转账给盗盗10 btc” 、“小B转账给盗盗20 btc” 、“小C转账给盗盗25 btc”都将被视为已经使用过的交易记录——从此被贴上“无效”的标签,意味着这些交易记录将永远不会再被追溯到。

我们最后一次重申,只是希望让你加深印象:拥有数字货币=拥有交易记录!

通过设计巧妙的精巧密码学保证数据安全

记录着交易信息的小纸条借助区块这个载体,在分布式的网络中以不同的轨迹错综复杂的传递,我们前面说了,你真正拥有的数字资产实际上是一段交易信息,而不是你常规意义上理解的货币。所以这个过程就需要重点解决两个问题: 接受到的这条交易记录在传输过程没有被其他人所篡改 接受到的这条交易记录确实是由发起交易的人所创造

在这里,我们需要事先引入两个知识点,可能稍微有点难消化,但都是计算机领域较为成熟的和基础的概念。

第一个知识点:SHA256()函数。你只需要知道,任意长度的字符串、甚至文件体本身经过SHA256函数工厂的加工,都会输出一个固定长度的字符串;同时,输入的字符串或者文件稍微做一丢丢的改动,SHA256() 函数给出的输出结果都将发生翻天覆地的改变。注意,SHA256()函数是公开的,任何人都能使用。
上图,仅仅一个小数点的变化,输出的结果已经翻天覆地

第二个知识点:非对称加密。你也只需要了解,任何人手里都有两把钥匙,其中一把只有自己知道,叫做“私钥”,以及一把可以公布于众,叫做“公钥”;通过私钥加密的信息,必须通过公钥才能解密,连自己的私钥也无解。公钥可以通过私钥生成多把。

有了这些知识点的加持,上面两个问题开始变得有解。下面我们来看下内部是如何扭转和工作的吧,这里拿“小A 转账给了小B 100元钱” 举例:
第一步 :小A会先用SHA256函数对自己的小纸条进行处理,得到一个固定长度的字符串,这个字符串就等价于这张小纸条。 第二步 :小A使用只有自己知道的那一把私钥,对上面固定长度的字符串进行再加密,生成一份名叫数字签名的字符串,这份数字签名能够充分证明是基于这张小纸条的。你可以这么理解,在现实中,你需要对某一份合同的签署,万一有人拿你曾经在其他地方留下的签名复制粘贴过来怎么办?!最好的办法,就是在你每一次签名的时候,故意在字迹当中留下一些同这份合同存在某种信息关联的小细节,通过对小细节的观察可以知道这个签名有没有被移花接木。步骤一和步骤二的结合就是为了生成这样一份有且仅针对这条小纸条有效的签名。 第三步: 小A将「明文的小纸条」、刚刚加密成功的「数字签名」,以及自己那把可以公布于众的「公钥」打包一起发给小B。 第四步: 当小B收这三样东西,首先会将明文的小纸条进行SHA256()处理,得到一个字符串,我们将其命名为“字符串2”。然后,小B使用小A公布的公钥,对发过来的数字签名进行解密,得到另外一个“字符串1”。通过比对“字符串1”和“字符串2”的一致性,便可充分证明:小B接受到的小纸条就是小A发出来的小纸条,这张小纸条在中途没有被其他人所篡改;且这张小纸条确实是由小A所编辑。

可以看得出来,加解密的过程几乎是一环套一环,中途任何环节被篡改,结果都是大相径庭。借助这一连串的机制,其实已经能够很好的在公开、匿名、彼此不信任的分布式网络环境中解决数字交易过程中可能遇到的很多问题。这个环节可能确实有点难理解,现在,我需要你停下来,静下心,花上几分钟闭目慢慢回味其中设计精湛的地方。

掌握了这部分知识以后,我们在这里回答一下前面没有解释清楚的问题,「节点对区块的检验」检验的到底是什么?实际上就是: 检验区块内的交易记录签名是否准确(是否被篡改) 检验区块内的交易记录输入值是否“有效”(是否使用过) 检验区块内的交易记录输入值的数字之和是否大于等于输出值的数字 …

# 重回“区块”和“区块链”的世界

好了,对小纸条和交易记录的研究我们点到为止,其实信息量已经是巨大的了,让我们合上盖子,重回较大的实体、继续聊聊“区块”和“区块链”的话题。还记得,咱们在一开始讲到关于区块的特征吗?区块创造后被埋在地下,需要经过节点们马不停蹄的挖采、而且是凭运气的挖采才有可能获得——不仅仅如此,事实上他还有其他很多神奇的地方,比如说: 凭空产生的区块在刚刚创建的时候会形成一股强大的黑洞效应,它会尝试将这段时间全世界各个节点上产生的所有小纸条(交易记录)统统吸进来;在合上区块盖子之前,同时会在区块内放上一些数字货币以及其他一些东西。 区块拥有一个唯一的ID,但它只会在这个区块被节点成功从地下挖出来之后创建。这个ID至少会跟「区块内所有小纸条的集合」、「即将与之相连的上一个区块ID」以及「挖矿节点的运气值」等因素相关。既然前面我们已经简单了解了“SHA256()函数”这个东西,这里不妨透露给大家:“区块ID = SHA256(‘区块内所有小纸条的集合’+’即将与之相连的上一个区块ID’+‘挖矿节点的运气值’+’…’)” ;基于先前掌握的知识,然后你应该知道区块内任意一张小纸条的信息稍微做改动、或者节点挖矿运气好一点坏一点等等,当前区块的ID都会 “ biu~ ”的发生改变。

基于上述1、2点,如果阅读足够仔细的同学可能会有些头大。在文章开头为了更好的描述,我在设计简化区块链系统的时候故意模棱两可了几个概念,这也许已经误导到了部分同学。这里不得不停下来和你一起修正下之前在你大脑中已经构建的区块链世界观。我们前面讲道,“在节点的视野里,大概每十分钟会凭空产生一个建立在自己平行宇宙世界的神奇区块”。如何正确去理解这句话呢?——拥有上帝之眼的你,可以这么拆解问题、看待问题: 同一个周期内,全网并不是产生唯一的一个区块等待挖掘;每个节点事实上都在周期性的创造区块和挖出区块;只是在某一个节点的视野里,它不能感知到另外一个节点上区块的产生。为何这里要特别强调“在某一个节点的视野里”,就是因为我们刚刚讲到,从区块的视角来说,区块的凭空产生,是基于即将与之相连的上一个区块ID;而从节点的视角来看,区块的凭空产生是基于当前节点区块链末尾的那个区块ID产生的。 全网会尽力控制在一个周期内只有一个节点能够成功挖出区块,但是不能够完全避免多个节点同时挖出区块的可能性;如何尽力控制?比如说,当大伙挖矿的热情高涨、工作效率提高,区块会被埋在更深更广的地方等。简而言之,通过提高工作难度,来维持这个平衡。另外,值得注意的:产生区块、挖出区块、校验区块,他们的时间周期近乎相同。
对于想从技术角度更加深入理解“区块”、“挖矿”本质的同学们,你们可以移步至我的专栏《 探索比特币“挖矿”和“区块”的数学本质 》,其中涉及到一些比较复杂的数学和技术细节,相信阅读完那部分内容之后,你对区块链会有更加透彻的认知。当然,对于绝大多数的吃瓜群众,看完那边内容可能会让你更加困惑,如果你不是十分的喜欢追根究底的话,我建议你还是直接选择跳过那块吧。至少在我看来,即便少了那部分内容,也不影响我们去理解区块链的魅力。

分叉

现在,我们终于对“区块”这个概念有了更全面的认识,文章开头讲的故事就可以继续展开来絮叨絮叨:

假如几乎同一时间,「中国上海浦东新区张衡路」上的节点和「美国纽约曼哈顿第五大道」上的节点异口同声喊出来:“我挖到区块了!里面的小纸条都是有效的!奖励归我!”。其他节点也几乎同时参与了对这两个区块的校验,结果发现这俩都没毛病,各节点也开始犯困,因为在他们的视野里他们并不清楚最后哪一个区块应该会被主链接纳。算了!都连在自己区块链尾巴上吧,这时尴尬了,区块链硬生生的被分叉了!
产生分叉

你肯定在想,那还得了,这种情况继续下去,每个节点的区块以及他们整理维护的小纸条都将变得不一样,这已经严重违背了区块链世界里第一大最基本原则——所有节点共同维护同一份数据。所以,为了解决这个问题,区块链世界引入了一条新的规则——拥有最多区块的支链将是真正被认可有价值的,较短的支链将会被直接Kill掉。

我们大伙都知道挖矿的过程存在巨大的工作量(如果没有任何难度,把区块扔在人群中,必然同一时间发现区块的节点数量将大大增加,也就会产生无数的支链,通过这个例子,你大概也就能够明白,比特币的区块链世界为什么需要设置工作难度了吧),并且在计算机的硅基世界里,不可能出现所谓 “同时” 的概念,哪怕纳秒的差别,那也总是会有先后顺序。所以理论上,“分叉”的这种僵局很快会在下一个区块被挖掘出来(以及校验区块)的时候被打破,实在不行下下个,或者下下下个……总之机制可以让整个分叉的区块链世界迅速稳定下来。

“分叉”这种僵局在确认下一个区块(以及校验小纸条)的时候被打破,从而整个区块链世界迅速稳定下来

就上图而言,所有基于张衡路节点挖矿获得的区块以及后续区块的那条分支被视为有价值,最终会全部保留了下来;其他节点会统一效仿那个拥有更长分支链的节点所做的决策。另外,值得一提的是,同一时间,较短分支上的区块会立即丢弃,而里面的小纸条也会随之释放出来,被重新标记上“未确认”。

“双花”与“51%攻击”

你可能已经开始困惑或者有点兴奋,末尾几个区块的排序在修复过程中,因为时间差肯定会产生一些模棱两可的地方,这往往会给数据安全埋下一颗雷。一个最简单的假设——我记录的一张小纸条很不巧地被归在了一条较短的支链上,这条支链在竞争过程中理所当然输掉了比赛,区块被丢弃、小纸条被无情的贴上“未确认”的标签。在等待下次区块重新确认的过程中,这个时间差内,我,好像、似乎可以做点什么坏事 ԅ(¯﹃¯ԅ) ,就比如说“双花”(双花,花两次,双重支付的意思)

你脑海中也许很快浮过的这样的构想,可不可能通过下面这种方法触发双花问题的产生,从而让我不劳而获:
假设有一个名叫X-Man的坏家伙,他控制了一个计算机节点,这个节点拥有比地球上任何一个节点算力都强大的计算机集群。 首先,X-Man事先创造了一条独立的(不去广而告之)、含有比较多区块的链条。其中一个区块里放着“X-Man转账给X-Man 1000元”的纸条。 接着,X-Man跟张三购买了一部手机,他在小纸条上记录下“X-Man转账给张三1000元”。张三已经比一般的卖家谨慎了,他在这条信息被三次确认后(即三个区块被真实挖出、校验和连接)才将手机给了X-Man。按照我们之前的理解,这条交易记录已经板上钉钉永远无法被串改。 X-Man拿到手机之后,按下机房的开关,试图将先前已经创造的区块链条连接在自己这个节点区块链的末尾。 大功告成,X-Man拥有了一条更长的区块链条,那些较短、存放着“X-Man转账给张三1000元”的区块链,以及在区块链世界里那则真实转账行为被一同成功销毁。(???)

事实真的如此吗?在这里我可以很负责任的说,too young too simple,区块链世界规则的制定远比我们想象的要健全很多,还记得我们之前讲的“区块的ID至少会跟区块内所有小纸条的集合、即将与之相连的上一个区块ID、当前产生区块的时间戳以及挖矿节点的运气值等因素相关”。 在这里,正是因为打算连接到主链的过程中,主链会立马意识到,那条事先准备的链子(的第一个区块)的时间戳存在异常,不属于当前区块链世界里线性增长的时间戳,于是马上意识到这个事先准备的链子(的第一个区块)是无效的,需要重新计算。

在区块链的世界,重新计算的行为等同于把自己(节点)置身于同一个起跑线,跟世界上其他所有的节点一同竞争挖矿。你会说,我拥有更强大的计算能力,但是对不起,跟你竞争的对象并不是第五大道、南京西路、香榭丽舍大道上的某一个节点,而是全球所有算力的集合,在这个集合中,你拥有的算力永远都只是一个很小的子集。所以,根据区块链算力民主、少数服从多数的基本原则,这个构想将永远不会成立。

除非....

你控制着全球51%的算力,这也就是区块链世界里另外一个著名的概念,叫做“51%攻击”,但这也仅仅是一个理论值,在真实世界里这样的攻击我个人觉得是很难发动起来的,这里面就牵涉到很多经济、哲学甚至政治的因素。举个最简单的例子:X-Man为了回滚刚刚发生的一笔交易记录,成功发起了51%攻击,这意味着很快整个区块链系统将会崩盘,因为这次攻击已经严重伤害到人们对这套系统的信任,接着比特币开始暴跌至几乎一文不值;但是这个拥有51%算力的X-Man原本完完全全可以通过挖矿的方式获取更多收益,购买无数的iPhone手机。那他不是脑袋不是坏了还能是啥?对51%攻击话题感兴趣的同学可以阅读这篇文章《 什么是比特币51%攻击? 》。

至此,我觉得区块链最基础、最核心的知识已经全部讲完了(除了挖矿内部实现原理,作为一个遗憾留在这里,有时间会完善掉),相信你已经对它有了一个宏观的认识。另外,由于这篇文章采用了适当抽象、类举的叙事方式,中间或多或少有些地方会跟区块链底层严谨的技术实现有出入,欢迎大家来纠错。另外,也是受限于自己知识结构的缺失,这篇文章会随着我对区块链更深入认识后,随时进行修订,最后更新时间可参考该回答下方的时间戳。

--
问答部分

去中心化的系统中,到底是谁在发行货币?是无限量发行吗?
比特币的货币是通过挖矿(工作量证明)来发行的,总数量是通过程序写死了2100万个,而第一笔区块奖励也是硬编码写死的。矿工挖出一个区块所获得的奖励,每隔21万个区块将减少一半,按照平均10分钟挖出一个区块的执行效率,也就就说差不多每四年会锐减一次。2009年1月起每个区块奖励50个比特币,2012年11月减半为每个区块25个比特币,2016年7月减半为12.5个比特币。基于这个规则,到2140年,所有比特币(20,999,999,980)将全部发行完毕,之后不会再有新的比特币产生。

矿工节点的收益除了挖出区块以外还有哪些?
矿工节点的收益主要由两部分组成:1)挖出新区块的奖励;2)挖出新区块内所含交易的交易费。但就目前来说,一个区块内的交易费大概只占到矿工总收入的0.5%甚至更少,大部分收益主要还是来自于挖矿所得的比特币奖励。然而,随着挖矿奖励的递减,以及每个区块中包含的交易数量增加,交易费在矿工收益中所占的比重将会逐渐增加。在2140年之后,所有的矿工收益将完全由交易费构成。



参考 中心化与去中心化 https://www.douban.com/note/624421270/ 图说区块链 https://book.douban.com/subject/27084306/ 区块链是什么,如何简单易懂地介绍区块链? https://www.zhihu.com/question/37290469 什么是比特币51%攻击? http://8btc.com/article-1949-1.html 区块链与新经济:数字货币2.0时代 https://book.douban.com/subject/26804497/ 詳解比特幣原理和運行機制 https://www.youtube.com/watch?v=P4seQcP77H4 区块链是什么:从技术架构到哲学核心 https://v.qq.com/x/page/x0518nuh2z7_0.html 区块链核心算法解析 https://book.douban.com/subject/27081206/ 深入理解比特幣的安全性及程式交易安全性與相關的密碼學原理 https://www.youtube.com/watch?v=3w1Tg3B_oKQ 深度了解区块链——拜占庭将军问题深入探讨 https://wallstreetcn.com/articles/338061 精通比特币-挖矿与共识 http://zhibimo.com/read/wang-miao/mastering-bitcoin/Chapter08.html
区块链
2018-05-28 15:16:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
比特币的区块链里除了天文数字的钱包地址,到底还写了些什么?
1,这个5月20日的表白,怎么出现在了5月23日的交易中?很有可能是写晚了,或者给矿工的工钱少了?
慧慧520 时间: 2018-05-23 16:08:02 高度: 523972 TID: 76e86e6dc2c8a2e18ab30737d79667ca3c98b3f7d7e9a152be3395fc3d90b0cd
2,这个哥们是在宣传自己的网址?已经发了很多次了,有兴趣的可访问下面链接。
https://codepen.io/anon/pen/pVKajz?editors=0011
时间: 2018-05-24 05:33:30 高度: 524059 TID: dd7ccd8a4edc3e23c445c28bcf01c16478c3205089ac74ce22d152b3985120b4
3,这又是一个表白,关键是对方能看到么?
慢慢喜欢你,余生都是你——wmj
时间: 2018-05-23 16:39:49 高度: 523975 TID: 3acc966815023a9a41b5677c6b6d59ac6c144b3bedd99b8b2ab6ddee8bc3d9a1
4,纪念重要的日子,这个可不同寻常。多贵的大饼!
Happy Bitcoin Pizza Day!
时间: 2018-05-23 02:51:54 高度: 523892 TID: 4cb19b5f81d6f0d6a32df677a5a9434328ab75611b5583791a18ddaf30be3b24
5,一个出生证明:
Register_Birth: Marcela Eizerik Morais; March, 22, 2018, 10:56 am; Torrance, CA.
时间: 2018-05-20 00:15:09 高度: 523419 TID: fe5f6a8fbca5467f576c2aa8ef5a0eb02dfda8f7997de54cc3d804835c9f9e2a
6,又是一个表白,看起来似乎的国人,这个时间终于对了,5月20日
EW Wendy,I love you forever,This life only to meet you.~Charles Liu
时间: 2018-05-20 12:06:35 高度: 523492 TID: ff7974b6a81e452122bbf7a80e375c69d3bcba469948f5d80c74d9335449ed21

我是在这里看到的 http://www.bittimestamp.com/
区块链
2018-05-27 11:47:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
1、 运行项目成功截图: ![](https://static.oschina.net/uploads/space/2018/0524/174944_1Lyd_3209213.png)


点击进去详情如图:
好了就不截图了,直接搭建运行项目
2、执行命令之前环境 node 6.9.5-9.10.0 之间 和go环境 2.1 $ git clone https://gitee.com/mdxl/block\_bill\_cj.git 2.2 $ cd billEndorse/ 2.3 $ npm install 2.4 $ npm install -g bower 2.5 $ cd billEndorse/public/ng 2.6 $ bower install 2.7 $ cd billEndorse/ 2.8 $ ./setupFabricNetwork.sh 2.9 $ ./createChannelAndInstallChaincode.sh
如果最后一个命令爆错误,那么安装下jq插件,,mac则执行命令 brew install jq,具体mac和windows,linux 安装看这个网址:https://stedolan.github.io/jq/download/ 最后浏览器访问界面 2.10 [http://localhost:4000/ng/src/](http://localhost:4000/ng/src/)
账户:admin 密码:123456
账户:bob 密码:123456
项目地址摘自于:Hyperledger设计与应用一书中的项目。
区块链
2018-05-24 18:08:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
一、安装web3j $ brew tap web3j/web3j $ brew install web3j $ web3j _ _____ _ _ | | |____ (_) (_) __ _____| |__ / /_ _ ___ \ \ /\ / / _ \ '_ \ \ \ | | | / _ \ \ V V / __/ |_) |.___/ / | _ | || (_) | \_/\_/ \___|_.__/ \____/| |(_)|_| \___/ _/ | |__/ Usage: web3j version|wallet|solidity ...
二、安装solc
sudo npm install -g solc
三、生成.bin和.abi
solcjs /Users/shijun/Desktop/truffleWorkspace/eCommerce/contracts/ConfirmOrder.sol --bin --abi --optimze -o/Users/shijun/Desktop/truffleWorkspace/eCommerce_out
四、生成.java
$ web3j solidity generate --solidityTypes /Users/shijun/Desktop/truffleWorkspace/eCommerce_out/_Users_shijun_Desktop_truffleWorkspace_eCommerce_contracts_ConfirmOrder_sol_ConfirmOrderContract.bin /Users/shijun/Desktop/truffleWorkspace/eCommerce_out/_Users_shijun_Desktop_truffleWorkspace_eCommerce_contracts_ConfirmOrder_sol_ConfirmOrderContract.abi -o /Users/shijun/Desktop/truffleWorkspace/eCommerce_out -p www.membersheep.hk.web3j
=================================================================
web3j solidity generate --solidityTypes /Users/shijun/Desktop/truffleWorkspace/sheepCoin_out/_Users_shijun_Desktop_truffleWorkspace_sheepCoin_tokenecr20_sol_TokenERC20.bin /Users/shijun/Desktop/truffleWorkspace/sheepCoin_out/_Users_shijun_Desktop_truffleWorkspace_sheepCoin_tokenecr20_sol_TokenERC20.abi -o /Users/shijun/Desktop/truffleWorkspace/sheepCoin_out -p Shpcoin.web3j
web3j solidity generate --solidityTypes /Users/shijun/Desktop/truffleWorkspace/sheepCoin_out/_Users_shijun_Desktop_truffleWorkspace_sheepCoin_tokenecr20_sol_tokenRecipient.bin /Users/shijun/Desktop/truffleWorkspace/sheepCoin_out/_Users_shijun_Desktop_truffleWorkspace_sheepCoin_tokenecr20_sol_tokenRecipient.abi -o /Users/shijun/Desktop/truffleWorkspace/sheepCoin_out -p Shpcoin.web3j

五、将java文件放入项目
六、启动私有链

miner.start(1)
miner.stop()
区块链
2018-05-24 15:57:04
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>> brew tap web3j/web3j brew install web3j neo@MacBook-Pro ~ % web3j _ _____ _ _ | | |____ (_) (_) __ _____| |__ / /_ _ ___ \ \ /\ / / _ \ '_ \ \ \ | | | / _ \ \ V V / __/ |_) |.___/ / | _ | || (_) | \_/\_/ \___|_.__/ \____/| |(_)|_| \___/ _/ | |__/ Usage: web3j version|wallet|solidity ...
区块链
2018-05-24 11:48:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
最著名的两个以太坊通证标准是代币标准ERC20和数字资产标准ERC721。在本文中,除了介绍这两个流行的ERC标准,还将介绍其他一些针对特定应用场景的ERC20改进标准:ERC223、ERC621和ERC827。
什么是ERC?
ERC代表“Etuereum Request for Comment",这是Ethereum版的意见征求稿 (RFC),RFC是由互联网工程任务组 制定的一个概念。 RFC中的备忘录包含技术和组织注意事项。 对于ERC,意见征求稿中包括一些关于以太坊网络 建设的技术指导。
ERC是Ethereum开发者为以太坊社区编写的。 因此,ERC的创建流程中包括开发人员。 为了创建一个以太坊平台的标准, 开发人员应当提交了一个以太坊改进方案(EIP), 改进方案中包括协议规范和合约标准。 一旦EIP被委员会批准并 最终确定,它就成为ERC。 EIP的完整列表可以在 这里 找到。
最终确定的EIP为以太坊开发者提供了一套可实施的标准。 这使得智能合约可以遵循这些通用的接口标准来构建。 ERC-20是整个加密社区中最为人熟知的标准,在Ethereum平台之上发布的大多数通证( token )都使用它。
下面是以太坊通证标准及其扩展: ERC20 ERC223 ERC621 ERC721 ERC827 如果你希望 高效的 学习以太坊DApp开发,可以访问汇智网提供的 最热门 在线互动教程: 适合区块链新手的以太坊DApp实战入门教程 区块链+IPFS+Node.js+MongoDB+Express去中心化以太坊电商应用开发实战
其他更多内容也可以访问 这个以太坊博客 。
区块链
2018-05-03 20:43:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
最著名的两个以太坊通证标准是代币标准ERC20和数字资产标准ERC721。在本文中,除了 介绍这两个流行的ERC标准,还将介绍其他一些针对特定应用场景的ERC20改进标准:ERC223、 ERC621和ERC827。 如果你希望马上开始学习以太坊DApp开发,可以访问汇智网提供的出色的在线互动教程: 以太坊DApp实战开发入门 去中心化电商DApp实战开发
什么是ERC?
ERC代表“Etuereum Request for Comment",这是Ethereum版的意见征求稿 (RFC),RFC是由互联网工程任务组 制定的一个概念。 RFC中的备忘录包含技术和组织注意事项。 对于ERC,意见征求稿中包括一些关于以太坊网络 建设的技术指导。
ERC是Ethereum开发者为以太坊社区编写的。 因此,ERC的创建流程中包括开发人员。 为了创建一个以太坊平台的标准, 开发人员应当提交了一个以太坊改进方案(EIP), 改进方案中包括协议规范和合约标准。 一旦EIP被委员会批准并 最终确定,它就成为ERC。 EIP的完整列表可以在 这里 找到。
最终确定的EIP为以太坊开发者提供了一套可实施的标准。 这使得智能合约可以遵循这些通用的接口标准来构建。 ERC-20是整个加密社区中最为人熟知的标准,在Ethereum平台之上发布的大多数通证( token )都使用它。
ERC-20标准的内容
ERC-20标准中定义了以下函数接口: totalSupply():返回代币供给总量 balanceOf(address _owner):返回_owner的帐户余额 transfer(address _to,uint256 _value):并将数量为_value的代币转入地址_to并触发transfer事件 transferFrom(address _from,address _to,uint256_value):将地址_from中的_value数量的代币转入地址_to ,并触发transfer事件 approve(address _spender,uint256 _value):允许_spender提取限额_value的代币 allowance(address _owner,address _spender):返回_spender可从_owner提款的代币数量上限
以上函数将触发以下事件: transfer(address indexed _from,address indexed _to,uint256 _value):每次进行代币转账时都会触发 approval(address indexed _owner,address indexed _spender,uint256 _value):调用approve()方法将触发该事件
ERC-20于2015年提出并于2017年9月正式实施。这是代币标准化的一个很好的起点。 然而,开发者社区 已经注意到它存在一些缺陷和漏洞,此外,还有一些场景它不能很好的满足。因此陆续提出了其他的ERC标准。
ERC-223 状态:打开 建议日期:3/5/2017
开发人员Dexaran在一篇文章中详细描述了ETC20不适合的两种场景:
“在ERC20中执行交易有两种方式: transfer函数。 approve + transferFrom机制。
通证余额只是通证合约中的一个变量。
通证的交易是合约内部变量的变化。 转出账户的余额将减少,转入账户的余额将增加。
交易发生时, transfer()函数不会通知转入账户。 因此转入账户将无法识别传入的交易! 我写了一个例子,可以展示这一导致未处理的交易和资金损失的过程 。
因此,如果接收账户是合约,那么必须使用approve + transferFrom机制来发送通证。 如果接受账户是外部拥有帐户,则必须通过transfer函数发送通证。 如果选择了错误的机制, 通证将卡在合约内(合约将不会识别交易),没有办法来提取这些卡壳的通证。“
他对这个问题提出的解决方案包含在ERC-223中 。 它与ERC-20标准非常相似,但解决了上述问题。 当通证转移到智能合约账户时,该合约的特殊函数tokenFallback() 允许接收方合约拒绝令牌或触发 进一步的操作。 在大多数情况下,这可以用来代替approve()函数。
ERC-621 状态:打开 建议日期:2017/5/1
ERC-621是ERC-20标准的扩展。 它增加了两个额外的功能, increaseSupply和decreaseSupply 。 这可以增加和减少流通中的令牌供应。 ERC-20只允许单一的通证发放事件。 这将供应量限制在 一个固定的不可改变的数目。 ERC-621建议totalSupply应当是可修改的。
ERC-721 状态:打开 建议日期:9/22/2017
ERC-721与ERC-20和ERC-223都大不相同。 它描述了一个不可互换的通证。 这意味着每个通证是完全不同的, 并且每个通证对不同的用户都有不同的价值。 理解这种通证的一个方法就是回忆CryptoKittes。 每一个数字猫 都是独立的,其价值取决于其稀缺性和用户的购买欲。
ERC-721令牌可用于任何交易所,但通证价值是“每个通证的唯一性和稀缺性所决定的结果”。标准中规定的接口 函数包括name、symbol、totalSupply、balanceOf、ownerOf、approve、takeOwnership 、 transfer 、tokenOfOwnerByIndex 和tokenMetadata 。 它还定义了两个事件: Transfer和Approval 。 Gerald Nash的 这篇文章很好地解释了 可互换性的概念。
ERC-827 状态:打开 建议日期:1/12/2018
ERC-20标准的另一个扩展是ERC-827。 它允许转让通证并允许持有人允许第三方使用通证。 以太坊上的通证可以被 其他应用程序重复使用,这其中也包括钱包和交易所。 当需要支持第三方动态消费限额调整时这一点非常有用。 最重要的是,由于ERC-827是ERC-20的延伸,它也与ERC-20兼容。
一些提议的接口函数包括: transferFrom(address _from,address _to,uint256 _value,bytes _data) returns (bool success) approve(address _spender,uint256 _value,bytes _data) returns (bool success)
原文链接: 以太坊通证标准简介:ERC20,/ERC721/ERC223/ERC621/ERC827
区块链
2018-05-03 11:21:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
> 如果你希望马上开始学习以太坊DApp开发,可以访问汇智网提供的出色的在线互动教程:
>
>- [以太坊DApp实战入门教程](http://xc.hubwiz.com/course/5a952991adb3847553d205d1?affid=oschina7878)
>- [以太坊去中心化电商应用开发实战](http://xc.hubwiz.com/course/5abbb7acc02e6b6a59171dd6?affid=oschina7878)
智能合约开发是以太坊开发的核心,而代币合约的编写是智能合约开发的核心,用solidity开发一个代币合约的例子是学习以太坊开发智能合约时必须掌握的。
以太坊的应用被称为去中心化应用(DApp),DApp的开发主要包括两大部分:
智能合约的开发
用户界面的开发
在本文中,我们将介绍智能合约的开发语言solidity。
让我们先从一个非常基础的例子开始,不用担心你现在还一点都不了解,我们将逐步了解到更多的细节。
```
contract SimpleStorage {
uint storedData;
function set(uint x) {
storedData = x;
}
function get() constant returns (uint retVal) {
return storedData;
}
}
```
在Solidity中,一个合约由一组代码(合约的函数)和数据(合约的状态)组成。合约位于以太坊区块链上的一个特殊地址。
uint storedData; 这行代码声明了一个状态变量,变量名为storedData,类型为 uint (256bits无符号整数)。你可以认为它就像数据库里面的一个存储单元,跟管理数据库一样,可以通过调用函数查询和修改它。在以太坊中,通常只有合约的拥有者才能这样做。在这个例子中,函数 set 和 get 分别用于修改和查询变量的值。
跟很多其他语言一样,访问状态变量时,不需要在前面增加 this. 这样的前缀。
这个合约还无法做很多事情(受限于以太坊的基础设施),仅仅是允许任何人储存一个数字。而且世界上任何一个人都可以来存取这个数字,缺少一个(可靠的)方式来保护你发布的数字。任何人都可以调用set方法设置一个不同的数字覆盖你发布的数字。但是你的数字将会留存在区块链的历史上。稍后我们会学习如何增加一个存取限制,使得只有你才能修改这个数字。
编写代币合约
接下来的合约将实现一个形式最简单的加密货币。任何人都可以发送货币给其他人,不需要注册用户名和密码,只要有一对以太坊的公私钥即可。
```
contract Coin {
//关键字“public”使变量能从合约外部访问。
address public minter;
mapping (address => uint) public balances;
//事件让轻客户端能高效的对变化做出反应。
event Sent(address from, address to, uint amount);
//这个构造函数的代码仅仅只在合约创建的时候被运行。
function Coin() {
minter = msg.sender;
}
function mint(address receiver, uint amount) {
if (msg.sender != minter) return;
balances[receiver] += amount;
}
function send(address receiver, uint amount) {
if (balances[msg.sender] < amount) return;
balances[msg.sender] -= amount;
balances[receiver] += amount;
Sent(msg.sender, receiver, amount);
}
}
```
这个合约引入了一些新的概念,让我们来逐个介绍。
```
address public minter;`
```
这行代码声明了一个可公开访问的状态变量,类型为address。address类型的值大小为160 bits,不支持任何算术操作。适用于存储合约的地址或其他人的公私钥。public关键字会自动为其修饰的状态变量生成访问函数。没有public关键字的变量将无法被其他合约访问。另外只有本合约内的代码才能写入。自动生成的函数如下:
```
function minter() returns (address) { return minter; }
```
当然我们自己增加一个这样的访问函数是行不通的。编译器会报错,指出这个函数与一个状态变量重名。
下一行代码创建了一个public的状态变量,但是其类型更加复杂:
```
mapping (address => uint) public balances;
```
该类型将一些address映射到无符号整数。mapping可以被认为是一个哈希表,每一个可能的key对应的value被虚拟的初始化为全0.这个类比不是很严谨,对于一个mapping,无法获取一个包含其所有key或者value的链表。所以我们得自己记着添加了哪些东西到mapping中。更好的方式是维护一个这样的链表,或者使用其他更高级的数据类型。或者只在不受这个缺陷影响的场景中使用mapping,就像这个例子。在这个例子中由public关键字生成的访问函数将会更加复杂,其代码大致如下:
```
function balances(address _account) returns (uint balance) {
return balances[_account];
}
```
我们可以很方便的通过这个函数查询某个特定账号的余额。
```
event Sent(address from, address to, uint value);
```
这行代码声明了一个“事件”。由send函数的最后一行代码触发。客户端(服务端应用也适用)可以以很低的开销来监听这些由区块链触发的事件。事件触发时,监听者会同时接收到from,to,value这些参数值,可以方便的用于跟踪交易。为了监听这个事件,你可以使用如下代码:
```
Coin.Sent().watch({}, '', function(error, result) {
if (!error) {
console.log("Coin transfer: " + result.args.amount +
" coins were sent from " + result.args.from +
" to " + result.args.to + ".");
console.log("Balances now:\n" +
"Sender: " + Coin.balances.call(result.args.from) +
"Receiver: " + Coin.balances.call(result.args.to));
}
}
```
注意在客户端中是如何调用自动生成的 balances 函数的。
这里有个比较特殊的函数 Coin。它是一个构造函数,会在合约创建的时候运行,之后就无法被调用。它会永久得存储合约创建者的地址。msg(以及tx和block)是一个神奇的全局变量,它包含了一些可以被合约代码访问的属于区块链的属性。msg.sender 总是存放着当前函数的外部调用者的地址。
最后,真正被用户或者其他合约调用,用来完成本合约功能的函数是mint和send。如果合约创建者之外的其他人调用mint,什么都不会发生。而send可以被任何人(拥有一定数量的代币)调用,发送一些币给其他人。注意,当你通过该合约发送一些代币到某个地址,在区块链浏览器中查询该地址将什么也看不到。因为发送代币导致的余额变化只存储在该代币合约的数据存储中。通过事件我们可以很容易创建一个可以追踪你的新币交易和余额的“区块链浏览器”。
区块链
2018-04-23 21:50:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
如果你不喜欢浪费时间在开发环境的搭建上,可以使用汇智网的在线教程: 以太坊DApp实战开发入门 去中心化电商DApp实战开发
一、安装DApp开发环境
1.1 安装Node.js
我们使用官方长期支持的8.10.0LTS版本,点击这个链接下载32位安装包,32位安装包即可用于32位系统,也可用于64位系统。 如果你确认你的系统是64位,也可以下载64位包装包。 下载后直接安装即可。安装完毕,打开一个控制台窗口,可以使用node了: C:
区块链
2018-04-23 17:38:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
Hyperledger也能实现Token代币
本文节选自电子书《Netkiller Blockchain 手札》
Netkiller Blockchain 手札
本文作者最近在找工作,有意向致电 13113668890
Mr. Neo Chan, 陈景峯(BG7NYT)
中国广东省深圳市龙华新区民治街道溪山美地 518131 +86 13113668890
文档始创于2018-02-10
版权 © 2018 Netkiller(Neo Chan). All rights reserved.
版权声明
转载请与作者联系,转载时请务必标明文章原始出处和作者信息及本声明。
微信订阅号 netkiller-ebook (微信扫描二维码) QQ:13721218 请注明“读者”
QQ群:128659835 请注明“读者” 网站:http://www.netkiller.cn
内容摘要
这一部关于区块链开发及运维的电子书。
为什么会写区块链电子书?因为2018年是区块链年。
这本电子书是否会出版(纸质图书)? 不会,因为互联网技术更迭太快,纸质书籍的内容无法实时更新,一本书动辄百元,很快就成为垃圾,你会发现目前市面的上区块链书籍至少是一年前写的,内容已经过时,很多例子无法正确运行。所以我不会出版,电子书的内容会追逐技术发展,及时跟进软件版本的升级,做到内容最新,至少是主流。
这本电子书与其他区块链书籍有什么不同?市面上大部分区块链书籍都是用2/3去讲区块链原理,只要不到 1/3 的干货,干货不够理论来凑,通篇将理论或是大谈特谈区块链行业,这些内容更多是头脑风暴,展望区块链,均无法落地实施。本书与那些书籍完全不同,不讲理论和原理,面向应用落地,注重例子,均是干货。
电子书更新频率?每天都会有新内容加入,更新频率最迟不会超过一周,更新内容请关注 https://github.com/netkiller/netkiller.github.io/commits/master
本文采用碎片化写作,原文会不定期更新,请尽量阅读原文。
http://www.netkiller.cn/blockchain/index.html
您的打赏是我的写作动力:http://www.netkiller.cn/blockchain/donations.html
==============================
Hyperledger Fabic 也能实现Token代币
33.2.14.2. 积分通正(代币)
我发现用以太坊思维,将以太坊代币合约搬到 hyperledger 上,一样可以实现代币的功能,这个代币除了不能上交易所,基本满足我们替代积分系统的需求,下面是我写了这样一个合约,在超级账本上实现类似以太坊的代币转账功能。 package main import ( "bytes" "encoding/json" "fmt" "strconv" "github.com/hyperledger/fabric/core/chaincode/shim" sc "github.com/hyperledger/fabric/protos/peer" ) // Define the Smart Contract structure type SmartContract struct { } type Token struct { Owner string `json:"Owner"` TotalSupply uint `json:"TotalSupply"` TokenName string `json:"TokenName"` TokenSymbol string `json:"TokenSymbol"` BalanceOf map[string]uint `json:"BalanceOf"` } func (token *Token) initialSupply(){ token.BalanceOf[token.Owner] = token.TotalSupply; } func (token *Token) transfer (_from string, _to string, _value uint){ if(token.BalanceOf[_from] >= _value){ token.BalanceOf[_from] -= _value; token.BalanceOf[_to] += _value; } } func (token *Token) balance (_from string) uint{ return token.BalanceOf[_from] } func (token *Token) burn(_value uint) { if(token.BalanceOf[token.Owner] >= _value){ token.BalanceOf[token.Owner] -= _value; token.TotalSupply -= _value; } } func (token *Token) burnFrom(_from string, _value uint) { if(token.BalanceOf[_from] >= _value){ token.BalanceOf[_from] -= _value; token.TotalSupply -= _value; } } func (token *Token) mint(_value uint) { token.BalanceOf[token.Owner] += _value; token.TotalSupply += _value; } func (s *SmartContract) Init(stub shim.ChaincodeStubInterface) sc.Response { return shim.Success(nil) } func (s *SmartContract) initLedger(stub shim.ChaincodeStubInterface) sc.Response { token := &Token{ Owner: "netkiller", TotalSupply: 10000, TokenName: "代币通正", TokenSymbol: "COIN", BalanceOf: map[string]uint{}} token.initialSupply() tokenAsBytes, _ := json.Marshal(token) stub.PutState("Token", tokenAsBytes) fmt.Println("Added", tokenAsBytes) return shim.Success(nil) } func (s *SmartContract) transferToken(stub shim.ChaincodeStubInterface, args []string) sc.Response { if len(args) != 3 { return shim.Error("Incorrect number of arguments. Expecting 2") } tokenAsBytes, _ := stub.GetState(args[0]) token := Token{} json.Unmarshal(tokenAsBytes, &token) token.transfer(args[1],args[2],args[3]) tokenAsBytes, _ = json.Marshal(token) stub.PutState(args[0], tokenAsBytes) return shim.Success(nil) } func (s *SmartContract) balanceToken(stub shim.ChaincodeStubInterface, args []string) sc.Response { if len(args) != 1 { return shim.Error("Incorrect number of arguments. Expecting 1") } tokenAsBytes, _ := stub.GetState(args[0]) token := Token{} json.Unmarshal(tokenAsBytes, &token) amount := token.balance(args[1]) return shim.Success(amount) } func (s *SmartContract) Invoke(stub shim.ChaincodeStubInterface) sc.Response { // Retrieve the requested Smart Contract function and arguments function, args := stub.GetFunctionAndParameters() // Route to the appropriate handler function to interact with the ledger appropriately if function == "balanceToken" { return s.balanceToken(stub, args) } else if function == "initLedger" { return s.initLedger(stub) } else if function == "transferToken" { return s.transferToken(stub, args) } return shim.Error("Invalid Smart Contract function name.") } // The main function is only relevant in unit test mode. Only included here for completeness. func main() { // Create a new Smart Contract err := shim.Start(new(SmartContract)) if err != nil { fmt.Printf("Error creating new Smart Contract: %s", err) } }
合约代码的测试 func main(){ token := &Token{ Owner: "netkiller", // 代币管理者 TotalSupply: 10000, // 代币发行总量 TokenName: "积分连", // 代币名称 TokenSymbol: "NEO", // 代币符号 NEO BalanceOf: map[string]uint{}} token.initialSupply() // 初始化代币 fmt.Println(token.balance("netkiller")) // 查询余额 token.transfer("netkiller","neo", 100) // 转账,这里账号使用用户ID,没有使用以太坊钱包那样的哈希值,因为哈希值不便于记忆。 fmt.Println(token.balance("netkiller")) fmt.Println(token.balance("neo")) }
我们可以建立很多套这样的比,例如水果币,蔬菜币,流量币...
开发一个小型交易所难度也不大,让用户在交易所中交易这些币。
区块链
2018-03-15 21:56:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
原文链接
区块链技术入门,涉及那些编程语言?在本文中,将介绍比特币、超级账本Fabric和以太坊这三种区块链中,分别使用什么开发语言来进行智能合约编程,并提供你进一步学习的资源链接。
比特币
比特币是第一个真正意义上的区块链,不过,从严格意义上来讲,它对智能合约的开发者是不友好的。
可以用一种低门槛的编程语言 Bitcoin Script 在比特币系统上编写智能合约。每个比特币地址都对应着一个Bitcoin Script程序。看起来是这样: IF 2 3 CHECKMULTISIG ELSE "30d" CHECKSEQUENCEVERIFY DROP CHECKSIG ENDIF
另一种较高级别的语言是Ivy,它可以编译成Bitcoin Script。Ivy能够帮助你编写自定义的比特币地址,这种地址与隔离见证(SegWit)兼容,在比特币协议(包括签名检查、hash特征值(commitment)和时间锁)的支持下,可以执行任意条件组合。例如: contract EscrowWithDeplay{ sender: PublicKey recipient: PublicKey, escrow: PublicKey, delay: Duration, val: Value }{ clause transfer(sig1: Signature, sig2: Signature){ verify checkMultiSig([sender, recipient, escrow],[sig1, sig2]) unlock val } clause timeout(sig: Signature){ verify checkSig(sender, sig) verify older(delay) unlock val } }
Ivy的github地址: https://github.com/ivy-lang/ivy-bitcoin
比特币“虚拟机”——协议中负责执行Bitcoin Script程序的一部分——与以太坊或者Chain Protocol等其它智能合约平台的虚拟机相比(功能)更加有限,其指令系统甚至不是图灵完备的。但Bitcoin Script的确提供了一组很有用的基础原语(primitives)——签名校验、哈希计算以及相对和绝对的时间锁——另外还能对这些原语进行自由组合。
超级账本fabric
fabric是超级账本大家庭中最成熟的一个区块链项目,主要用于行业链、联盟联或私有链,它不需要通过挖矿来形成共识,因此可以达到很高的交易速度。
在fabric中,智能合约被称为链码(Chaincode),实质上是控制区块链网络中的不同实体或相关方如何相互交互或交易的业务逻辑。简言之,链代码将业务网络交易封装在代码中。可以调用链代码来设置和获取账本或 world state。
超级账本可以使用go、java或者nodejs来开发智能合约,不过支持最好的还是go语言。下面是使用go开发的一个简单地fabric智能合约: package main import "fmt" import "github.com/hyperledger/fabric/core/chaincode/shim" type SampleChaincode struct { } func (t *SampleChaincode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) { return nil, nil } func (t *SampleChaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) { return nil, nil } func (t *SampleChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) { return nil, nil } func main() { err := shim.Start(new(SampleChaincode)) if err != nil { fmt.Println("Could not start SampleChaincode") } else { fmt.Println("SampleChaincode successfully started") } }
frabric的智能合约可以使用一个go中的类实现,它必须要实现约定的借口Init和Query。
Init 方法 在链代码首次部署到区块链网络时调用,将由部署自己的链代码实例的每个对等节点执行。而只要在区块链状态上执行任何读取/获取/查询操作,就会调用 Query 方法。
访问这里了解更多关于fabric的智能合约开发的相关信息: Fabric Chaincode
以太坊
以太坊是第一个提供完善的智能合约开发框架的区块链,因此它也被称为区块链2.0的代表。事实上,目前绝大多数的区块链应用,包括ICO代币发行,都是基于以太坊来实现的智能合约应用。
以太坊有四种专用语言可以用来开发智能合约: Solidity ,受JavaScript 启发 Serpent ,受Python启发 Mutan,受Go 启发 LLL 受Lisp 启发
这四种语言都是为面向合约编程而从底层开始设计的语言,但从目前的发展来看,Solidity已经称为以太坊智能合约开发当之无愧的首选语言。
Solidity的语法类似于JavaScript,这降低了学习门槛,易于被掌握和使用,因为JavaScript是Web开发者的常用语言。例如,下面是一个使用Solidity开发的简单但完整的智能合约: pragma solidity ^0.4.21; contract HelloWorld { string hello = "Hello World!!!"; event say(string _value); function sayHello() public { emit say(hello); } }
合约代码第一行指定该合约使用的Solidity版本为0.4.21,不支持高于0.4.21版本的Solidity特性。
在Solidity中,contract关键字包含的代码段即表示一个智能合约,它拥有一些成员变量和函数,看起来非常类似于传统的面向对象开发中的类。 如果你希望马上开始学习以太坊智能合约和应用开发,可以访问汇智网提供的出色的在线互动教程: 以太坊智能合约与应用实战开发入门 以太坊去中心化电商应用实战开发
区块链
2018-04-25 12:39:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
比原项目仓库:
Github地址: https://github.com/Bytom/bytom
Gitee地址: https://gitee.com/BytomBlockchain/bytom
在开发合约的过程中你们有没有遇到一些问题呢?比如编译合约的过程中不能实时动态的去检查我们所编译的合约文件是否正确,那么我今天就教大家一种很方便的方法。可以让小伙伴们在编写合约的过程中,可以随时检查自己的合约编写是否正确。
首先要确保我们有go语言开发环境且版本高于1.8,如果没有搭建go语言开发环境,请自行百度。确保go支持的版本已经正确安装: $ go version $ go env GOROOT GOPATH
获取源代码并编译,参考链接: https://github.com/Bytom/equity
编译完了以后我们可以在equity下执行: ./equity/equity --help
获取合约的命令帮助。返回的截图如下:
图中标的1,2,3,4 分别表示执行命令所带参数的含义。图中3对应的 instance参数表示实例化合约,4对应的shift表示指定执行合约里面具体的函数。然后在项目下面创建一个合约文件(合约文件最好不带任何后缀名),如下图:
然后编写合约,我是用vim编译的合约,大家可以自行选择用vim或者编辑器编写合约。如果编译合约的过程中存在问题,请参考合约开发文档: https://bytom.github.io/mydoc_RPC_call.cn.html 。下图是我在vim中编写的合约。
合约编写完了以后,如果合约编写错误或者存在语法错误,会出现如下图所示的情况,请检查自己编写的合约
检查无误以后,在对应的目录下面执行合约文件,然后就可以输出下图所示的二进制。说明合约编写成功
大家有没有发现很简单呢?快点实践起来吧!如果在开发的过程中遇到问题,请在我们的社区联系我们: https://github.com/Bytom/
区块链
2018-11-14 12:34:06
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
1
摘要
开发实战|3步教你在以太坊上开一家宠物店(附流程+代码) 介绍了如何获取宠物商店的TRUFLLE框架代码,并完成部署的过程。
但是这个是已经成熟的代码框架,一般用户要开发自己的项目。那如何借用宠物商店成熟框架完成自有DAPP的搭建呢?我们以tiny熊老师的一个姓名/年龄智能合约用例来呈现方法。
2
需求描述
我们要实现一个用户姓名和年纪的输入和呈现页面,能更新智能合约上的用户名和年龄。重新输入用户名和年纪,点击按钮可更新智能合约的这2个变量信息。
3
操作步骤
3.1 创建目录,下载框架
首先创建好目录,下载宠物商店的代码框架。 duncanwang@ubuntu:~/work$ mkdir name-age duncanwang@ubuntu:~/work$ cd name-age duncanwang@ubuntu:~/work/name-age$ truffle unbox pet-shop Downloading... Unpacking... Setting up... Unbox successful. Sweet! Commands:   Compile:        truffle compile   Migrate:        truffle migrate   Test contracts: truffle test   Run dev server: npm run  devduncanwang@ubuntu:~/work/name-age$
3.2 创建智能合约代码
新建一个InfoContract.sol智能合约文件,并把它更新到./contracts目录下。 pragma solidity ^0.4.24; contract InfoContract {     string name;     uint age;     event Instructor(string name, uint age);     function setInfo(string _name, uint _age) public {         name = _name;         age = _age;         emit Instructor(name, age);     }     function getInfo() public view returns(string, uint) {         return (name, age);     } }
3.3 增加合约相关的部署和测试代码
1) 增加合约部署测试
文件2_info_contract.js到./migrations目录,代码如下,表示contract InfoContract合约部署。 var MyContract = artifacts.require("./InfoContract.sol"); module.exports = function(deployer) {   // deployment steps   deployer.deploy(MyContract); };
2) 增加测试文件 pragma solidity ^0.4.24; import "truffle/Assert.sol"; import "truffle/DeployedAddresses.sol"; import "../contracts/InfoContract.sol"; contract TestInfoContract {    InfoContract info = InfoContract(DeployedAddresses.InfoContract());    string name;    uint age;    function testInfo() {      info.setInfo("ABC", 10);      (name, age) = info.getInfo();      Assert.equal(name, "ABC", "设置名字出错");      Assert.equal(age, 10, "设置年龄出错");    } }
3)修改配置文件
因为默认ganache-cli的端口为8545,所以需要修改truffle.js的端口号由7545 变为8545。 module.exports = {   // See   // for more about customizing your Truffle configuration!   networks: {     development: {       host: "127.0.0.1",       port: 8545,       network_id: "*" // Match any network id     }   } };
否则测试时会有找不到客户端提示。 duncanwang@ubuntu:~/work/name-age$ truffle test Could not connect to your Ethereum client. Please check that your Ethereum client:     - is running     - is accepting RPC connections (i.e., "--rpc" option is used in geth)     - is accessible over the network     - is properly configured in your Truffle configuration file (truffle.js)
3.4 验收测试智能合约
1)参考宠物商店的文章代码 , 在一个窗口启动一个ganache-cli 钱包 。 duncanwang@ubuntu:~/work/name-age$ cd .. duncanwang@ubuntu:~/work$ ganache-cli >>trace.log
2)编译智能合约
然后启动另外一个窗口命令行,输入一下命令。 duncanwang@ubuntu:~/work/name-age$ truffle compile Compiling ./contracts/InfoContract.sol... Compiling ./contracts/Migrations.sol... Writing artifacts to ./build/contracts
3)智能合约验收命令。
测试成功的提示说明: duncanwang@ubuntu:~/work/name-age$ truffle test Using network 'development'. Compiling ./contracts/InfoContract.sol... Compiling ./test/TestInfoContract.sol... Compiling truffle/Assert.sol... Compiling truffle/DeployedAddresses.sol... Compilation warnings encountered: /home/duncanwang/work/name-age/test/TestInfoContract.sol:12:4: Warning: No visibility specified. Defaulting to "public".     function testInfo() {    ^ (Relevant source part starts here and spans across multiple lines).   TestInfoContract     ✓ testInfo (838ms)   1 passing (5s)
3.5 完成前端页面
完成以下2个文件的修改更新和上传。
1) index.html
把宠物商店的index.html的代码删除,替换为本文需要的框架代码。                    First Truffle DApp Demo          
        

First Truffle DApp Demo

        

                                                          
                   
2) app.js
然后修改app.js的代码,完成智能合约的执行和调用作用。 App = {   web3Provider: null,   contracts: {},   init: function() {     return App.initWeb3();   }, /*加载web3*/   initWeb3: function() {     if (typeof web3 !== 'undefined') {          App.web3Provider = web3.currentProvider          web3 = new Web3(App.web3Provider);      } else {          App.web3Provider = new Web3.providers.HttpProvider("http://localhost:9545")          web3 = new Web3(App.web3Provider);      }      return App.initContract();   }, /*初始化合约,获取合约,不需要使用at()的方式;   显示合约的姓名和年龄信息*/   initContract: function() {     $.getJSON('InfoContract.json', function(data){       App.contracts.InfoContract = TruffleContract(data);       App.contracts.InfoContract.setProvider(App.web3Provider);       App.getInfo();       App.watchChanged();     });     App.bindEvents();   },   getInfo: function() {     App.contracts.InfoContract.deployed().then(function(instance) {       return instance.getInfo.call();     }).then(function(result) {       $("#loader").hide();       $("#info").html(result[0]+' ('+result[1]+' years old)');       console.log(result);     }).catch(function(err) {       console.error(err);     });   }, /*点击按钮更新姓名和年龄,则需要更新到智能合约上*/   bindEvents: function() {     $("#button").click(function() {         $("#loader").show();         App.contracts.InfoContract.deployed().then(function(instance) {           return instance.setInfo($("#name").val(), $("#age").val(), {gas: 500000});         }).then(function(result) {           return App.getInfo();         } ).catch(function(err) {           console.error(err);         });       });   },   watchChanged: function() {     App.contracts.InfoContract.deployed().then(function(instance) {       var infoEvent = instance.Instructor();       return infoEvent.watch(function(err, result) {         $("#loader").hide();         $("#info").html(result.args.name +' ('+ result.args.age +' years old)');       });     });   }   } $(function(){   $(window).load(function() {       App.init();   }); });
3.6 测试验收前端和合约交互代码
1) 部署合约
合约部署成功。 duncanwang@ubuntu:~/work/name-age$ truffle migrate Using network 'development'. Running migration: 1_initial_migration.js   Deploying Migrations...   ... 0x5b3cd41a7fa7c58361172ac797412469a10edfbe721d8d81988f19282c9cb6e4   Migrations: 0x92b6ecd23aa98fad36926c12ec701f9aaa0933f4 Saving successful migration to network...   ... 0x826fcd5b72b48435bf4f9941305727e52b0b7290631ba7b39f642027b1ee6947 Saving artifacts... Running migration: 2_info_contract.js   Deploying InfoContract...   ... 0x9943dd7b90207bd9fd1e85524d1d0227f18a92269d73f5a2141cb71c22dda1e9   InfoContract: 0x191391c710e1b632e40b4f2267dbc0f3bdb2bed4 Saving successful migration to network...   ... 0x7e11f6e32585524e338e73439e4026c7c766625e5d23d56a4c90f8a11e5001ed Saving artifacts...
2)安装并启动lite-server
1] 安装lite-server
【定义】lite-server 是轻量级的,仅适用于开发 的 node 服务器, 它仅支持 web app。 它能够为你打开浏览器, 当你的html或是JavaScript文件变化时,它会识别到并自动帮你刷新浏览器, 还能使用套接字自动注入变化的CSS, 当路由没有被找到时,它将自动后退页面。
参考:如何在WINDOWS环境下搭建以太坊开发环境( https://www.jianshu.com/p/683ea7d62a39),完成MetaMask和liteServer的安装。
duncanwang @ubuntu :~/work/name-age$ npm install lite-server --save-dev
成功安装的输出结果如下: npm WARN pet-shop@1.0.0 No description npm WARN pet-shop@1.0.0 No repository field. npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.4 (node_modules/fsevents): npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.4: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"ia32"}) + lite-server@2.4.0 added 342 packages from 273 contributors in 56.82s **2] 在新的窗口完成lite-server的启动。** duncanwang@ubuntu:~/work/name-age$ npm run dev > pet-shop@1.0.0 dev /home/duncanwang/work/name-age > lite-server ** browser-sync config ** { injectChanges: false,   files: [ './**/*.{html,htm,css,js}' ],   watchOptions: { ignored: 'node_modules' },   server:     { baseDir: [ './src', './build/contracts' ],      middleware: [ [Function], [Function] ] } } [Browsersync] Access URLs:  --------------------------------------        Local: http://localhost:3000     External: http://10.225.18.149:3000  --------------------------------------           UI: http://localhost:3001  UI External: http://localhost:3001  -------------------------------------- [Browsersync] Serving files from: ./src [Browsersync] Serving files from: ./build/contracts [Browsersync] Watching files...
3)打开主页
输入lite-server提示的主页地址: http://10.225.18.149:3000
可以看到页面输出信息。
4)更新姓名和年龄
输入框输入姓名和年龄:王登辉,18 ,点击更新按钮,会弹出MEATMASK的交易提示,确认交易。
确认交易后,姓名和年龄信息会更新。
4
总结
本文仅从操作层面讲解了如何利用宠物商店的模板样例,快速重构一个含前端的DAPP页面。
具体WEB.3J的接口函数及定义,参考文章《 从宠物商店案例看DAPP架构和WEB3.JS交互接口 》。
所有工程的源码已上传到知识星球,有需要的同学可加入下载。
本文作者:HiBlock区块链技术布道群- 辉哥
原文发布于简书
加微信baobaotalk_com,加入技术布道群
区块链
2018-11-13 23:44:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
本文首发于 深入浅出区块链社区 原文链接: 使用 ethers.js 开发以太坊 Web 钱包 3 - 展示钱包信息及发起签名交易) 原文已更新,请读者前往原文阅读
以太坊去中心化网页钱包开发系列,将从零开始开发出一个可以实际使用的钱包,本系列文章是理论与实战相结合,一共有四篇: 创建钱包账号 、 账号Keystore文件导入导出 、 展示钱包信息及发起签名交易 、 发送Token(代币) ,这是第三篇介绍使用ethers.js的钱包对象获取相关信息及发起你离线交易。
使用 Provider 连接以太坊网络
我们前面两篇文章介绍创建(或导入)钱包账号的过程都是是离线的,即不需要依赖以太坊网络即可创建钱包账号,但如果想获取钱包账号的相关信息,比如余额、交易记录,发起交易的话,就需要让钱包连上以太坊的网络。
不管是在 Web3 中,还是Ethers.js 都是使用 Provider 来进行网络连接的,Ethers.js 提供了集成多种 Provider 的方式: Web3Provider: 使用一个已有的web3 兼容的Provider,如有MetaMask 或 Mist提供。 EtherscanProvider 及 InfuraProvider: 如果没有自己的节点,可以使用Etherscan 及 Infura 的Provider,他们都是以太坊的基础设施服务提供商,Ethers.js 还提供了一种更简单的方式:使用一个默认的provider, 他会自动帮我们连接Etherscan 及 Infura。 let defaultProvider = ethers.getDefaultProvider('ropsten');
连接Provider, 通常有一个参数network网络名称,取值有: homestead , rinkeby , ropsten , kovan , 关于Provider的更多用法,可以参考 Ethers.js Provider 。 JsonRpcProvider 及 IpcProvider: 如果有自己的节点可以使用,可以连接主网,测试网络,私有网络或Ganache,这也是本系列文章使用的方式。
使用钱包连接Provider的方法如下: // 连接本地的geth 节点,8545是geth 的端口 var provider = new ethers.providers.JsonRpcProvider("http://127.0.0.1:8545"); // wallet 为前两篇文章中生成的钱包对象, activeWallet就是后面可以用来请求余额发送交易的对象 var activeWallet = wallet.connect(App.provider); 启动geth的需要注意一下,需要使用 --rpc --rpccorsdomain 开启 RPC通信及跨域,
展示钱包详情:查询余额及Nonce
连接到以太坊网络之后,就可以向网络请求余额以及获取账号交易数量,使用一下API: activeWallet.getBalance().then(function(balance) { }); activeWallet.getTransactionCount().then(function(transactionCount) { });
activeWallet就是后面可以用来请求发送交易的对象

钱包详情:

地址:
余额:
Nonce:
刷新

js处理的逻辑就是获取信息之后,填充相应的控件,代码如下: var inputBalance = $('#wallet-balance'); var inputTransactionCount = $('#wallet-transaction-count'); $("#wallet-submit-refresh").click(function() { // 获取余额时, 包含当前正在打包的区块 activeWallet.getBalance('pending').then(function(balance) { // 单位转换 wei -> ether inputBalance.val(ethers.utils.formatEther(balance, { commify: true })); }, function(error) { }); activeWallet.getTransactionCount('pending').then(function(transactionCount) { inputTransactionCount.val(transactionCount); }, function(error) { }); }); // 模拟一次点击获取数据 $("#wallet-submit-refresh").click();
发送签名交易
之前我们有一篇文章: 如何使用Web3.js API 在页面中进行转账 介绍过发起交易,不过当时的签名是利用MetaMask来完成的,现在我们要完成一个钱包,必须要发送一个签名交易,签名交易也称为离线交易(因为这个过程可以离线进行:在离线状态下对交易进行签名,然后把签名后的交易进行广播)。
尽管 Ethers.js 提供了非常简洁的API来发送签名交易,但是探究下简洁API背后的细节依然会对我们有帮助,这个过程大致可分为三步: 构造交易 交易签名 发送(广播)交易
构造交易
先来看看一个交易长什么样子: const txParams = { nonce: '0x00', gasPrice: '0x09184e72a000', gasLimit: '0x2710', to: '0x0000000000000000000000000000000000000000', value: '0x00', data: '0x7f7465737432000000000000000000000000000000000000000000000000000000600057', // EIP 155 chainId - mainnet: 1, ropsten: 3 chainId: 3 }
发起交易的时候,就是需要填充每一个字段,构建这样一个交易结构。 to 和 value : 很好理解,就是用户要转账的目标及金额。 data : 是交易时附加的消息,如果是对合约地址发起交易,这会转化为对合约函数的执行,可参考: 如何理解以太坊ABI nonce : 交易序列号 chainId : 链id,用来去区分不同的链(分叉链)id可在 EIP-55 查询。 nonce 和 chainId 有一个重要的作用就是防止重放攻击,如果没有nonce的活,收款人可能把这笔签名过的交易再次进行广播,没有chainId的话,以太坊上的交易可以拿到以太经典上再次进行广播。
gasPrice 和 gasLimit : Gas是以太坊的工作计费机制,是由交易发起者给矿工打包的费用。上面几个参数的设置比较固定,Gas的设置(尤其是gasPrice)则灵活的多。
gasLimit 表示预计的指令和存储空间的工作量,如果工作量没有用完,会退回交易发起者,如果不够会发生 out-of-gas 错误。 一个普通转账的交易,工作量是固定的,gasLimit为21000 ,合约执行gasLimit则是变化的,也许有一些人会认为直接设置为高一点,反正会退回,但如果合约执行出错,就会吃掉所有的gas。幸运的是web3 和 ethers.js 都提供了测算Gas Limit的方法,下一遍 发送代币
gasPrice 是交易发起者是愿意为工作量支付的 单位 费用,矿工在选择交易的时候,是按照gasPrice进行排序,先服务高出价者,因此如果出价过低会导致交易迟迟不能打包确认,出价过高对发起者又比较亏。
web3 和 ethers.js 提供一个方法 getGasPrice() 用来获取最近几个历史区块gas price的中位数,也有一些第三方提供预测gas price的接口,如: gasPriceOracle 、 ethgasAPI 、 etherscan gastracker ,这些服务通常还会参考当前交易池内交易数量及价格,可参考性更强,
常规的一个做法是利用这些接口给用户一个参考值,然后用户可以根据参考值进行微调。
交易签名
在构建交易之后,就是用私钥对其签名,代码如下: const tx = new EthereumTx(txParams) tx.sign(privateKey) const serializedTx = tx.serialize()
代码参考 ethereumjs-tx
发送(广播)交易
然后就是发送(广播)交易,代码如下: web3.eth.sendRawTransaction(serializedTx, function (err, transactionHash) { console.log(err); console.log(transactionHash); });
通过这三步就完成了发送签名交易的过程,ethers.js 里提供了一个简洁的接口,来完成所有这三步操作(强调一下,签名已经在接口里帮我们完成了),接口如下: activeWallet.sendTransaction({ to: targetAddress, value: amountWei, gasPrice: activeWallet.provider.getGasPrice(), gasLimit: 21000, }).then(function(tx) { });
用ethers.js 实现发送交易
先来看看发送交易的UI界面:

以太转账:

发送至:
金额:
发送

上面主要定义了两个文本输入框及一个“发送“按钮,在点击发送时运行一下(关键)代码: var inputTargetAddress = $('#wallet-send-target-address'); var inputAmount = $('#wallet-send-amount'); var submit = $('#wallet-submit-send'); submit.click(function() { // 得到一个checksum 地址 var targetAddress = ethers.utils.getAddress(inputTargetAddress.val()); // ether -> wei var amountWei = ethers.utils.parseEther(inputAmount.val()); activeWallet.sendTransaction({ to: targetAddress, value: amountWei, // gasPrice: activeWallet.provider.getGasPrice(), (可用默认值) // gasLimit: 21000, }).then(function(tx) { console.log(tx); }); })
https://my.oschina.net/u/3724910
区块链
2018-11-09 10:43:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
1
摘要
网站太多,各种用户名/密码实在记不住。所以我们逐渐接受了BAT账号的授权登录功能。在以太坊DAPP应用中,也可以使用MetaMask实现授权后一键登录功能。MetaMask是去中心化钱包,授权信息不会如BAT中心一样存在被收集利用的问题。
本文从技术层面讲清楚原理,并结合代码说明如何实现。
2
授权一键式登录的利弊分析
我们往往被自己的密码难住,越来越抵制传统的电子邮件/密码注册流程。通过微信,QQ,支付宝,Facebook,Google或GitHub一键式社交登录功能可以省去记住密码或者密码泄露的而风险。当然,它也需要权衡利弊。
社交媒体登录集成的优点: 没有更麻烦的填表。 无需记住另一个用户名/密码对。 整个过程需要几秒钟而不是几分钟。
社交媒体登录集成的缺点: 由于用户的信息是从外部提供商处加载的,因此这会对提供商如何使用所有这些个人数据产生巨大的隐私担忧。例如,在撰写本文时,Facebook正面临着数据隐私问题( https://www.reuters.com/article/us-facebook-privacy-costs-analysis/privacy-issues-emerge-as-major-business-risk-for-facebook-idUSKBN1GW01F)。
加密猫( https://www.cryptokitties.co/ )游戏中,用户不需要输入用户名,密码就可以建立自己的账户体系,进行登录交易。
签名导入-cancel
本文介绍下这个方法的原理和代码实现,使用MetaMask扩展的一键式加密安全登录流程,所有数据都存储在我们自己的后端。我们称为“使用MetaMask登录”。
3
** 如何使用Metamask进行一键式登录流程**
一键式登录流程的基本思想是,通过使用私钥对一段数据进行签名,可以很容易地通过加密方式证明帐户的所有权。如果您设法签署由我们的后端生成的精确数据,那么后端将认为您是该钱包地址的所有者。因此,我们可以构建基于消息签名的身份验证机制,并将用户的钱包地址作为其标识符。
如果它看起来不太清楚,那就没问题了,因为我们会逐一解释它: MetaMask浏览器扩展 登录流程如何工作 为什么登录流程有效 让我们一起建立它 今天就可以投入生产了 移动设备的缺点
请注意,虽然我们将使用连接到以太坊区块链( https://www.toptal.com/ethereum)的工具(MetaMask,以太坊钱包地址),但此登录过程实际上并不需要区块链:它只需要其加密功能。话虽如此,随着MetaMask成为如此受欢迎的扩展(https://twitter.com/metamask_io/status/942816957920829440),现在似乎是介绍此登录流程的好时机。
4
MetaMask浏览器扩展
如果您已经知道MetaMask是什么,请跳过本节。
MetaMask( https://metamask.io/)是一个浏览器插件,可作为MetaMask Chrome扩展( https://chrome.google.com/webstore/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn)或Firefox附加组件使用(https://addons.mozilla.org/en-US/firefox/addon/ether-metamask/)。它的核心是它作为以太坊钱包:通过安装它,您将可以访问一个独特的以太坊钱包地址,您可以使用它开始发送和接收以太币或ERC20通证。
但MetaMask不仅仅是以太坊钱包。作为浏览器扩展,它可以与您正在浏览的当前网页进行交互。它通过在您访问的每个网页中注入一个名为web3.js( https://github.com/ethereum/web3.js/)的JavaScript库来实现。注入后,web3将通过window.web3的JavaScript代码为你访问的每个网页提供一个对象。要查看此对象,只需在Chrome或Firefox DevTools控制台键入window.web3(如果已安装MetaMask),结果如下图。
web3.js
Web3.js是以太坊区块链的JavaScript接口。有以下功能: 获取最新的区块号(web3.eth.getBlockNumber) 检查MetaMask上的当前活动帐户(web3.eth.coinbase) 获取任何帐户的余额(web3.eth.getBalance) 发送交易(web3.eth.sendTransaction) 使用当前帐户的私钥对消息进行签名(web3.personal.sign) ......还有获取更多接口说明: https://github.com/ethereum/wiki/wiki/JavaScript-API
安装MetaMask时,任何前端代码都可以访问所有这些功能,并与区块链进行交互( https://www.toptal.com/ethereum-smart-contract)。他们被称为dapps或DApps(去中心化的应用程序,有时甚至写成“ĐApps”)。
与DApp开发相关: 时间锁定钱包:以太坊智能合约简介 ( https://www.toptal.com/ethereum-smart-contract/time-locked-wallet-truffle-tutorial)
web3.js中的大多数函数都是读函数(get block, get balance, etc.),web3立即给出响应。但是,某些功能(如web3.eth.sendTransaction和web3.personal.sign)需要当前帐户使用其私钥对某些数据进行签名。这些函数触发MetaMask显示确认弹窗,以仔细检查用户是否知道他或她正在签名的内容。
让我们看看如何使用MetaMask。要进行简单测试,请在DevTools控制台中粘贴以下行:
web3.personal.sign(web3.fromUtf8("你好,我是辉哥!!"), web3.eth.coinbase, console.log);
此命令表示:使用coinbase帐户(即当前帐户)将我的消息(从utf8转换为十六进制)进行签名,并以打印作为回调函数打印出签名。输入回车后,将出现MetaMask弹窗,如果点击签名按钮,将打印签名的消息。
MetaMask确认弹出窗口
我们将web3.personal.sign在登录流程中使用。
关于这一部分的最后一点说明:MetaMask将web3.js注入到您当前的浏览器中,但实际上还有其他独立的浏览器也会注入web3.js,例如Mist( https://github.com/ethereum/mist)。但是,在我看来,MetaMask为普通用户提供了探索dapps的最佳用户体验和最简单的转换。
5
登录流程如何工作
这是如何做到的呢?这部分内容讲说服你,证明这种方式是安全的。所以为什么部分的介绍就比较短了。
如前面所述,我们将忘记区块链。我们有一个传统的Web 2.0客户端 - 服务器RESTful架构。我们将做出一个假设:访问我们的前端网页的所有用户都安装了MetaMask。有了这个假设,我们将展示无密码加密安全登录流程的工作原理。
第1步:修改用户模型(后端)
首先,我们的User模型需要有两个新的必填字段:publicAddress和nonce。此外,publicAddress需要具有唯一性。你可以保持平常username,email和password字段,特别是如果你想平行实现您MetaMask登录电子邮件/密码登录,但它们是可选的。
如果用户希望使用MetaMask登录,则注册过程也会略有不同,因为注册时publicAddress将是必填字段。不过请放心,用户永远不需要手动输入publicAddress钱包地址,因为它可以通过web3.eth.coinbase变量来提取。
第2步:生成随机数(后端)
对于数据库中的每个用户,在nonce字段中生成随机字符串。例如,nonce可以是一个大的随机整数。
第3步:用户获取他们的随机数(前端)
在我们的前端JavaScript代码中,假设存在MetaMask,我们可以访问window.web3。因此,我们可以通知web3.eth.coinbase获取当前MetaMask帐户的钱包地址。
当用户单击登录按钮时,我们向后端发出API调用以检索与其钱包地址关联的随机数。像带参数获取例如GET /api/users?publicAddress=${publicAddress}应该做的事情那样。当然,由于这是一个未经身份验证的API调用,因此后端应配置为仅显示此路由上的公共信息包括nonce。
如果先前的请求未返回任何结果,则表示当前钱包地址尚未注册。我们需要先通过POST /users传递publicAddress请求消息体来创建一个新帐户。另一方面,如果有结果,那么我们存储它的nonce。
第4步:用户签署Nonce(前端)
一旦前端接收nonce到先前API调用的响应,它将运行以下代码:
web3.personal.sign(nonce, web3.eth.coinbase, callback);
这将提示MetaMask显示用于签名消息的确认弹出窗口。随机数将显示在此弹出窗口中,以便用户知道她或他有没有签署某些恶意数据。
当她或他接受签名时,将使用带签名的消息(称为signature)作为参数调用回调函数。然后前端进行另一个API调用POST /api/authentication,传递一个带有signature和publicAddress的消息体。
第5步:签名验证(后端)
当后端收到POST /api/authentication请求时,它首先根据请求消息体中publicAddress获取数据库中的对应用户,特别是它相关的随机数nonce。
具有随机数,钱包地址和签名后,后端可以加密地验证( https://en.wikipedia.org/wiki/Digital_signature)用户已正确签署了随机数。如果确认是这种情况,那么用户已经证明了拥有钱包地址的所有权,我们可以考虑对她或他进行身份验证。然后可以将JWT或会话标识符返回到前端。
第6步:更改Nonce(后端)
为了防止用户使用相同的签名再次登录(如果它被泄露),我们确保下次同一用户想要登录时,她或他需要签署一个新的nonce。这是通过nonce为该用户生成另一个随机数并将其持久保存到数据库来实现的。
这就是我们管理nonce签名无密码登录流程的方法。
6
为什么登录流程有效
根据定义,身份验证实际上只是帐户所有权的证明。如果您使用钱包地址唯一地标识您的帐户,那么证明您加密方式拥有该帐户就非常简单。
为了防止黑客获取某个特定邮件及其签名(但不是您的实际私钥),我们会强制需要签名的消息满足以下条件: 由后端提供 定期改变
在我们的demo样例中,每次成功登录后我们都改变了它,但也可以设想基于时间戳的机制。
MetaMask登录流程的六个步骤概述。
7
demo代码实现
在本节中,我将逐一完成上述六个步骤。我将展示一些代码片段,以便我们如何从头开始构建此登录流,或者将其集成到现有的后端,而不需要太多努力。
为了本文的目的,我创建了一个小型演示应用程序。我正在使用的堆栈如下: Node.js,Express和SQLite(通过Sequelize ORM)在后端实现RESTful API。它在成功验证时返回JWT。 在前端反应单页面应用程序。
我尝试使用尽可能少的库。我希望代码足够简单,以便您可以轻松地将其移植到其他技术堆栈。
访问 https://login-with-metamask.firebaseapp.com/可以获得一个演示,也可以参考步骤搭建自己的本地工程。
第1步:修改用户模型(后端)
需要两个字段:publicAddress和nonce。我们初始化nonce为随机大数。每次成功登录后都应更改此号码。我还在username这里添加了一个可选字段,用户可以更改。 > .\backend\src\models
区块链
2018-11-14 22:55:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
概念解读
区块链几乎是数日间成为人尽皆知的名词,这个名词也勾起了我强烈的兴趣,但是通过在网上搜罗资料,多方阅读,发现很多介绍区块链的文献要么模棱两可,要么作者本身的理解也很有限,导致很多关键的问题叙述不清。本人花了一些时间总结归纳,希望可以给读者一个比较全面清晰的认识。

区块链的官方定义是:一个分布式账本,一种通过去中心化、去信任的方式集体维护一个可靠数据库的技术方案。那么对于圈外人该如何理解呢?以下我会详细描述一个区块链的产生过程和实现意义,从而给大家构建出一个清晰的区块链概念。我们先讲原理、再说特点、然后论用途、最后回归代码,这样你就会有一种恍然大悟的感觉。

我们以btc为例:“区块链”,顾名思义,就是由一个个区块依次连接起来组成的链条,可以类比为一条无限长度的直线铁链,每个铁环就是一个区块。那么区块的内容应该是什么呢?区块狭义上是有两种的,一个是普通区块,一个就是创世区块。创世区块就是一项区块链项目中的第一个区块,由于个人水平有限,对创世区块没有做过详细研究,但是根据我的了解,创世区块应该是具备与普通区块相似结构的,但会肯定会加入一些创始人想说的东西,并且在有些项目中可能会多一条记录,就是coin的发行量,例如swtc的6000亿数目就是写在创世区块之中的,一旦发行,无法修改。

那么,一个普通区块中到底有什么?
1.index:就是从0-n依次产生的数字,可以称之为链高度。
2.hash:一个长度为256位随机数,是这个区块的唯一编号。
3.previous hash:上一个区块的hash,一个普通区块有且仅有一个previous hash,这就是区块链之所以称为链的原因,就是这么一环套一环链接而成的。
4.tempstamp:用于记录该区块诞生的时间。
5.difficulty:直观体现创造该区块的难度。
6.nonce:随机数,用于产生下一个区块。
上述的都存在区块头中。
7.data:存储的交易记录。只有这个存在区块体中。

Ok,上述提到了一个区块需要具备的最基本的几条要素,可能你现在还处于一脸懵逼的状态:这些东西到底是怎么工作的呢?下面我将一步步分析区块链的工作过程,不过,这里要先问两个问题:为什么要产生新的区块?怎么产生新的区块?

为什么产生新区快?
之前说了,一个区块记录的就是一份账单,账单中存储着若干条交易记录,是买卖双方具体活动的最有力的证明,例如我们在淘宝上的购买记录,就是我们的消费账单。人们每天的消费记录是不断增长的,不可能永远放在一个区块里,那么跟现在的中心化存储机制还有什么区别?所以,随着买卖记录的不断增加,就需要不断产生新的区块来存储这些数据。

怎么产生新的区块?
我相信,最近除了区块链这个名词如雷贯耳以外,“挖矿”应该也没少听吧。挖矿实际上就是由那些矿工来生成新的区块的过程。在btc项目中,btc矿工挖矿成功(其实就是成功的创建了一个区块)就可以获得一定数量的被btc奖励,所以btc数量是在一定范围内慢慢增加的。在一般允许挖矿的区块链项目(也存在限制coin数量不允许挖矿的区块链项目)中,矿工的数量一般会大于6个,一般超过6个矿工认可的新区块就可以加入到区块链中。到此为止,有人会说:哇!btc这么值钱,挖矿不是很爽?其实不然,如果区块无限制的快速增加,会引起很大的问题,根据中本聪的设定,目前全网每10分钟只能产生一个新区块。而且这10分钟不是靠自己掐表算的,生成新的区块是需要大量的运算的,这10分钟是人家预先设计好的,让计算量大到全网10分钟一般只能产生一个。

好了,至此,区块链的基本概念已经介绍的差不多了,下面言归正传,讲下区块的工作流程:
1.如果A要和B达成一笔交易,比如A转给B一个btc,B给A打10w的RMB。A首先将自己的btc来源信息、交易人等发送给B,同时还要拷贝一份发到全网。什么?这样还有隐私可言吗?当然,聪明的中本聪当然不会犯这么低级的错误。在区块链中,每个交易个体(也可以理解为每个网络节点)都会有一对公钥和私钥,公钥相当于一个“收款地址”,而私钥是一个表明自己身份的256位的数字,目前一般是用sha265来生成的,这样,别人并不知道交易的双方是谁。发送报文时,发送方用一个哈希函数从报文文本中生成报文摘要,然后用自己的私钥对摘要进行加密,加密后的摘要将作为报文的数字签名和报文一起发送给接收方,接收方首先用与发送方一样的哈希函数从接收到的原始报文中计算出报文摘要,接着再用发送方的公钥来对报文附加的数字签名进行解密,如果这两个摘要相同、那么接收方就能确认该数字签名是发送方的。

2.那么此时,这笔交易是否就完成了呢?如果这就算完成了,那跟A直接用包裹装10w现金快递给B有什么区别呢?此时,全网的矿工都会得到这个交易记录,那么全网的矿工都会为了若干奖励开始创建区块的工作,矿工会利用hash函数生成一个256位的唯一编号赋予这个区块,但是这个编号并不是简简单单随便生成的。编号是根据区块的具体内容如交易内容、nonce等唯一确定的,换句话说,两块内容相同的区块所对应的编号一定是唯一的。可是你会问:这又怎么了?并不难啊。错!中本聪为了控制区块的生成时间,使区块的生成速率满足全网的每10分钟一个的标准,制定了严格的区块生成校验规则,也就是说,能不能生成一个成功的区块要看你的编号是否符合这个规则。例如:生成编号中的前n位必须为‘0’。

由于区块的交易内容是无法修改的,因此矿工们只能通过修改nonce去不断尝试这个函数,直到生成了一个成功的区块为止。如果当区块平均生成时间变快或者变慢,那么系统会对区块校验规则进行相应的调整,从而使平均的生成时间能够控制在规定范围。

如果一个矿工完成了一个区块,会立刻告知其他矿工,如果其他矿工此时没有完成新的区块生成,则会停下手头的工作,对区块进行验证,需要确认的信息主要有如下几点:

1).区块的编号有效;这个只要将区块放入哈希函数中,看产生的编号是否和该区块中的编号一致即可。
2).区块的前一个区块有效;之前提过,区块是一个串联的,每一个普通区块都会记载前一个区块的编号,这需要其他矿工对比当前的区块链的最后一个区块,看是否相同。
3).交易清单有效;就是说要验证A到底有没有这一个btc可以给B。在区块链的交易信息中,会记录交易中所有btc的前世今生,区块链可以做到追本溯源,因此每一个btc在哪里,为什么在这里都可以一目了然,所以这点也没问题。
当验证完一个全新的区块后,全网就会认为这个区块有效,会将它添加到现有的区块链末端,同时结束针对该区块的挖矿工作,投入到下一个挖矿周期中。
3.但是不难想象,这样的机制是存在冲突的隐患的,就是这么巧,两个矿工同时制作了一个正确的区块,那么此时不必二选一,可以将原来线性的区块链改成树状:

但是这样会导致未来在A、B后都会增加相应的区块,那么谁长谁将作为主链延伸下去,另一个也许会渐渐被遗忘,除非哪天它变得更长。
好啦,这就是区块链最基本的知识,接下来应该谈谈优缺点了。

世界上没有一样东西可以称为完美无瑕的,要知道区块链一样,虽然它被扣上了可以颠覆未来的帽子,但是仍然存在它的局限性:
1.时效性。很容易发现,区块链中存在很多的验证、传递环节,这就会导致其时效性较差。
2、能耗,这点也是显而易见的,区块链需要大量无用计算来控制区块的生成时间。所以区块链不适用于高时效的网络中。

至于区块链的优点,诸如安全、去中心化等等在网络上已经描述的非常清楚,这里就不再赘述。接下来我用一段python代码来简单实现一个挖矿的流程。

代码示例
首先创建一个表示区块链的类: class BlockChain: def __init__(self, initialHash): # init block chain self.chain = [] # init pitman self.pitmen = [] for i in range(6): self.pitmen.append(Pitman) # collect mine results self.results = [] # generate GenesisBlock self.new_block(initialHash)

初始化函数中的chain表示当前的区块链,我会在其中存储区块对象;pitmen表示为这个区块链服务的矿工们,这个列表中也会存有矿工对象;results则会存储每个阶段产生的区块;new_block方法是创建区块的方法,如果当前生成的区块为第一个区块,则产生创世区块。
下面看看区块链类型的方法: @property def last_block(self): if len(self.chain): return self.chain[-1] else: return None

last_block会返回当前区块链的最后一个区块对象。 def get_trans(self): return json.dumps({ 'sender': ''.join(random.sample(string.ascii_letters + string.digits, 8)), 'recipient': ''.join(random.sample(string.ascii_letters + string.digits, 8)), 'amount': random.randrange(1, 10000) })

get_trans方法则用来随机生成一份交易信息。 def new_block(self, initialHash=None): if initialHash: # generate Genesis Block block = Block() block.index = 0 block.nonce = random.randrange(0, 99999) block.previousHash = '0' block.difficulty = 0 block.transactionData = self.get_trans() guess = f'{block.previousHash}{block.nonce}{block.transactionData}'.encode() block.hash = hashlib.sha256(guess).hexdigest() block.time = time() self.chain.append(block) else: for i in range(len(self.pitmen)): pm = MyThread(target=self.pitmen[i].mine, args=(self.pitmen[i], len(self.chain), self.last_block.get_block()['Hash'], self.get_trans())) pm.start() pm.join() self.results.append(pm.get_result()) # show all blocks print("All blocks generated by pitmen:") for result in self.results: print(result[0].get_block()) # get new block firstblock = self.results[0][0] mintime = Decimal(self.results[0][1]) for i in range(1, len(self.results)): if Decimal(self.results[i][1]) < mintime: firstblock = self.results[i][0] else: continue self.chain.append(firstblock) self.results = []

这是生成区块的核心部分,这个方法主要分成两个部分:根据传参区分是否是创世区块,如果需要的是创世区块,那就由该类型自动生成一个区块占据区块链的头一个位置。如果需要生成的是普通区块,那么则会将一些基本信息分发给矿工们进行挖矿操作。我在这里设置了6个矿工,为了公平起见,这里也开了个多线程尽量让矿工们同时收到消息从而可以同时进行挖矿操作。按理说,最先挖矿成功的矿工会将消息发给其他矿工,其他矿工会立刻停止进行校验,但由于时间有限,这一步校验环节我没有实现。在这里,我允许所有矿工都完成工作,并提交成果和相应的工作时间,生成耗时最短的区块讲作为正确的区块添加到区块链上。本质上也是依照了“快者优先”的区块链生成原则。

说了半天,区块内部到底是什么样的呢? class Block: def __init__(self): self.index = None self.time = None self.difficulty = None self.nonce = None self.hash = None self.previousHash = None self.transactionData = None def get_block(self): return { 'Index': self.index, 'Time': self.time, 'Difficulty': self.difficulty, 'Hash': self.hash, 'Nonce': self.nonce, 'PreviousHash': self.previousHash, 'TransactionData': self.transactionData }

我用了一个相对简单的类型表示区块,在这里区块就是一个非常简单的数据结构,这里的所有字段在上述中已经有了详细的说明,因此不再赘述。
那么我们再看看矿工,毕竟矿工才是区块链的生产者和推动者,地位最为核心。矿工类中我设计了两个方法,一个mine方法,也就是挖矿的意思,用来生成新的区块,并会返回该区块生成的用时长短。 def mine(self, index, previousHash, transactionData): beginTime = time() block = Block() block.index = index block.previousHash = previousHash block.transactionData = transactionData block.difficulty, block.hash, block.nonce = self.generate_hash(previousHash, transactionData) block.time = time() endTime = time() return block, endTime - beginTime

另一个方法是hash生成的方法,生成原则我自己意淫了一个,大家莫怪,因为本人计算机的实在不给力,区块的成功标准很简单,就是用sha256生成的编码最后结尾是0就满足要求,如果改成00,那会半天看不到结果。
下面我们看下这套实例的运行结果,我设置了一个长度为6的区块链,由于第一个区块是创世区块,所以真正开始创建的区块是从第二个开始的,大家注意index。
这是6个矿工完成的第一区块: All blocks generated by pitmen: {'Index': 1, 'Time': 1516268156.5971138, 'Difficulty': 2, 'Hash': '01f505a276e3f55a868d9ee18f70bcff75429e1de70f5ab59471a3551cc67a30', 'Nonce': 91554, 'PreviousHash': '7532402844a1c130833a27600298d09a007d6124603cf44be9c05fcd5428c34a', 'TransactionData': '{"sender": "OY8z0Rrx", "recipient": "iSGFJsEm", "amount": 8723}'} {'Index': 1, 'Time': 1516268156.5971138, 'Difficulty': 5, 'Hash': 'c3ba406bad0d87f816f629830a15e2997638bfa230484c224e5470eaa24d8790', 'Nonce': 62372, 'PreviousHash': '7532402844a1c130833a27600298d09a007d6124603cf44be9c05fcd5428c34a', 'TransactionData': '{"sender": "9o8UMDLe", "recipient": "qTOQu7kv", "amount": 2746}'} {'Index': 1, 'Time': 1516268156.5981123, 'Difficulty': 5, 'Hash': '8ff243885e9017296aa2ef1a611ef5b3927ddce818cb7255a04ff3228c982c60', 'Nonce': 67644, 'PreviousHash': '7532402844a1c130833a27600298d09a007d6124603cf44be9c05fcd5428c34a', 'TransactionData': '{"sender": "kIqy1c8C", "recipient": "WSdK0EXh", "amount": 9329}'} {'Index': 1, 'Time': 1516268156.5981123, 'Difficulty': 3, 'Hash': 'ff9716bf9379e2ab7a8640419e7c7b7c7329a5e6e1bbf83a1249f49d070ca8b0', 'Nonce': 37336, 'PreviousHash': '7532402844a1c130833a27600298d09a007d6124603cf44be9c05fcd5428c34a', 'TransactionData': '{"sender": "vBwU0luH", "recipient": "d7o6cRCj", "amount": 5628}'} {'Index': 1, 'Time': 1516268156.5981123, 'Difficulty': 3, 'Hash': '3410c70c31f9bacbfcbd74d63f25f69f27d36075e2d44bddaa60bd72fa042e60', 'Nonce': 34617, 'PreviousHash': '7532402844a1c130833a27600298d09a007d6124603cf44be9c05fcd5428c34a', 'TransactionData': '{"sender": "yzcNpBnh", "recipient": "vbIr7SKo", "amount": 6387}'} {'Index': 1, 'Time': 1516268156.5981123, 'Difficulty': 27, 'Hash': '91e3dc3ef1a151557a1edd837528410b916362bcfb77dbb14dc54c8929f5a0d0', 'Nonce': 49121, 'PreviousHash': '7532402844a1c130833a27600298d09a007d6124603cf44be9c05fcd5428c34a', 'TransactionData': '{"sender": "p1MguhVz", "recipient": "gVSom4D3", "amount": 7356}'}
很明显前两个是最快的,为了简单,我在最快的里面随便选取一个,意思到了就行。大家可以看到,难度值,根据上文所说,这是反应一个区块生成的难易程度的,难度高的,在我这里会表示这个矿工为了得到这个区块进行了多少次尝试。看到这里也许你会问:为什么难度最大的时间并没有明显长呢?也就是用时并没有按照难度的增加而增加。我猜想应该是因为我的示例算法简单,因此结果也不是十分精确,如果计算量达到一定的规模,应该会有明显的差距。(如果有高人知道,可以回复我,在此谢过!)第三到第六个的区块创建结果格式是与之一样的,就不刷屏了。

最后看下整个区块链的结果: {'Index': 0, 'Time': 1516268156.5971138, 'Difficulty': 0, 'Hash': '7532402844a1c130833a27600298d09a007d6124603cf44be9c05fcd5428c34a', 'Nonce': 87688, 'PreviousHash': '0', 'TransactionData': '{"sender": "OuVCmHbs", "recipient": "kFxbwSLc", "amount": 503}'} {'Index': 1, 'Time': 1516268156.5971138, 'Difficulty': 2, 'Hash': '01f505a276e3f55a868d9ee18f70bcff75429e1de70f5ab59471a3551cc67a30', 'Nonce': 91554, 'PreviousHash': '7532402844a1c130833a27600298d09a007d6124603cf44be9c05fcd5428c34a', 'TransactionData': '{"sender": "OY8z0Rrx", "recipient": "iSGFJsEm", "amount": 8723}'} {'Index': 2, 'Time': 1516268156.5991132, 'Difficulty': 4, 'Hash': '098544436793881e8041c0c903c96c0055e16396113d73c63bc55e7ba78ec130', 'Nonce': 12875, 'PreviousHash': '01f505a276e3f55a868d9ee18f70bcff75429e1de70f5ab59471a3551cc67a30', 'TransactionData': '{"sender": "HJZSX1hk", "recipient": "j82k51yY", "amount": 3521}'} {'Index': 3, 'Time': 1516268156.6001143, 'Difficulty': 27, 'Hash': '7c10243223caf39bc5a6067de8d93f6ea46bad62c4a0fbcc0aa4e086585d8200', 'Nonce': 18663, 'PreviousHash': '098544436793881e8041c0c903c96c0055e16396113d73c63bc55e7ba78ec130', 'TransactionData': '{"sender": "cJrGxN5R", "recipient": "wkZI8QCv", "amount": 1224}'} {'Index': 4, 'Time': 1516268156.601114, 'Difficulty': 3, 'Hash': '60a099d3fe53e031800669fcc1d9b5ab6df1f80a40354135310a799892f1c3d0', 'Nonce': 51446, 'PreviousHash': '7c10243223caf39bc5a6067de8d93f6ea46bad62c4a0fbcc0aa4e086585d8200', 'TransactionData': '{"sender": "nCNJoy52", "recipient": "kYBT9f65", "amount": 3603}'} {'Index': 5, 'Time': 1516268156.605163, 'Difficulty': 2, 'Hash': '765f69163cf95584721015e3ce819c1980ce33752f8a4dea553d3bedd39f8920', 'Nonce': 31804, 'PreviousHash': '60a099d3fe53e031800669fcc1d9b5ab6df1f80a40354135310a799892f1c3d0', 'TransactionData': '{"sender": "FqOkiTEu", "recipient": "y9EDcSYA", "amount": 4185}'}

这就是由这6个矿工依次创建的六个区块,根据hash值环环相扣。
到底我想说的基本就结束了,最后我想说区块链是个神奇的技术,从听到它就深深的吸引着我,期望未来区块链可以真的带来巨大的变革。要知道,随着AI的兴起,区块链的问世,属于程序员的数字时代会进一步升华,互联网时代只是一个开始!谢谢阅读,本人水平有限,如果您发现问题或我理解偏差的地方可以及时指出,再次表示感谢。文章末尾会附上完整代码。 import hashlib import random import string import json import threading from decimal import Decimal from time import time class MyThread(threading.Thread): def __init__(self, target, args=()): super(MyThread, self).__init__() self.func = target self.args = args def run(self): self.result = self.func(*self.args) def get_result(self): try: return self.result except Exception: return None class BlockChain: def __init__(self, initialHash): # init block chain self.chain = [] # init pitman self.pitmen = [] for i in range(6): self.pitmen.append(Pitman) # collect mine results self.results = [] # generate GenesisBlock self.new_block(initialHash) @property def last_block(self): if len(self.chain): return self.chain[-1] else: return None def get_trans(self): return json.dumps({ 'sender': ''.join(random.sample(string.ascii_letters + string.digits, 8)), 'recipient': ''.join(random.sample(string.ascii_letters + string.digits, 8)), 'amount': random.randrange(1, 10000) }) def new_block(self, initialHash=None): if initialHash: # generate Genesis Block block = Block() block.index = 0 block.nonce = random.randrange(0, 99999) block.previousHash = '0' block.difficulty = 0 block.transactionData = self.get_trans() guess = f'{block.previousHash}{block.nonce}{block.transactionData}'.encode() block.hash = hashlib.sha256(guess).hexdigest() block.time = time() self.chain.append(block) else: for i in range(len(self.pitmen)): pm = MyThread(target=self.pitmen[i].mine, args=(self.pitmen[i], len(self.chain), self.last_block.get_block()['Hash'], self.get_trans())) pm.start() pm.join() self.results.append(pm.get_result()) # show all blocks print("All blocks generated by pitmen:") for result in self.results: print(result[0].get_block()) # get new block firstblock = self.results[0][0] mintime = Decimal(self.results[0][1]) for i in range(1, len(self.results)): if Decimal(self.results[i][1]) < mintime: firstblock = self.results[i][0] else: continue self.chain.append(firstblock) self.results = [] def show_chain(self): print('This is mine first block chain!') for block in self.chain: print(block.get_block()) class Block: def __init__(self): self.index = None self.time = None self.difficulty = None self.nonce = None self.hash = None self.previousHash = None self.transactionData = None def get_block(self): return { 'Index': self.index, 'Time': self.time, 'Difficulty': self.difficulty, 'Hash': self.hash, 'Nonce': self.nonce, 'PreviousHash': self.previousHash, 'TransactionData': self.transactionData } class Pitman: def mine(self, index, previousHash, transactionData): beginTime = time() block = Block() block.index = index block.previousHash = previousHash block.transactionData = transactionData block.difficulty, block.hash, block.nonce = self.generate_hash(previousHash, transactionData) block.time = time() endTime = time() return block, endTime - beginTime @staticmethod def generate_hash(previousHash, transactionData): difficulty = 0 nonce = random.randrange(0, 99999) guess = f'{previousHash}{nonce}{transactionData}'.encode() myhash = hashlib.sha256(guess).hexdigest() while myhash[-1] != '0': difficulty += 1 nonce += difficulty guess = f'{previousHash}{nonce}{transactionData}'.encode() myhash = hashlib.sha256(guess).hexdigest() return difficulty, myhash, nonce if __name__ == '__main__': chain = BlockChain(1) length = 5 for i in range(length): chain.new_block() chain.show_chain()

阅读原文
区块链
2018-10-26 13:54:00