狼爱上狸

我胡汉三又回来了

2019年5月17日 #

区块链被神化的伪概念

过去一年的热门话题没有什么比区块链技术更火了,但这里面有太多被神话、误解的地方,本文就详细从技术层面、极客思维方式(哲学)、社会学和经济学等多个维度的分析,来洞悉区块链技术的背后真相。

  下笔之前我几乎看过了所有主流媒体上的各种区块链文章,但我觉得没有一篇写的通俗易懂又全面。本文以论文的方式来阐述,虽然较长(可能阅读要花15分钟以上),不过看完后基本就能明白区块链怎么回事,特别是对到底是不是应该去投资虚拟货币会有更清晰的认识。

  01 区块链技术分析

  本节以比特币为例来说明区块链技术,如果你对技术不感兴趣,直接跳到02章节继续阅读,只需要知道结论:区块链就是用来实现一个虚拟货币记帐本,拥有比特币就是在这个帐本里面拥有区块里面的若干条数据记录。

  1.1 问题

  现在的区块链可能出了很多衍生的所谓新技术架构,但最终还是离不开那个不可修改的区块结构设计,所以这一节就以比特币来说明这些底层技术架构。看完这节,至少你能够解决以下疑惑:

  用普通话和别人讲清楚比特币的底层技术架构是什么?区块链是一种最近才被发明出来的新技术吗?

  挖矿是怎么一回事?

  比特币的交易过程如何?

  比特币钱包和比特币是什么关系?

  1.2 计算机不是前沿科学

  这有一个打假重要法则,鼓吹任何形式的单纯的计算机技术多么神奇的文章,都要打一个大大的问号。

  现在所有计算机都是图灵机,而图灵提出图灵机的论文都快100来年了。计算机领域不是所谓前沿科学,而是一种能大幅提高人们工作效率的工具。所以在信息领域,把从业人员也称为软件工程师、硬件工程师、IOS开发工程师和测试工程师等等。

  目前区块链技术和人工智能这二项技术已经被专家们吹到天上去了,我今天就先把区块链这层皮高科技的皮给扒了,以后有机会我再扒人工智能的。

  其实不管哪种计算机领域的技术都由二样东西组成:数据 和 算法。

  就拿人工智能来说,其实就是统计学在计算机的应用,吹的神乎其神的阿发狗在原理上其实就是蒙特卡洛树 + 基于贝叶斯网络的DeepMind,不过DeepMind取了个很牛的名字叫神经网络。

  当然知道原理和能做出来是完全不一样的,和很多工程建设一样,需要对应的很多基础平台和优秀的工程师,但归根结底是一个工程问题,不是科学问题。

  举这个例子只是想说明,没有必要去神话一项软件技术,计算机领域和很多传统的行业一样都是工程问题,甚至可能在工程管理水平上面还不如高铁和大型桥梁建设。

  1.3 比特币的数据结构

  比特币底层数据结构非常简单,是只要学过一点点计算机的人都懂的链表,特殊在用算法实现了不可修改只能往后追加。块与块之前就是链表结构,块内部是一个特殊的二叉树(Merlin Tree)结构,存了交易的流水信息。至于每一块里面的具体数据结构细节非专业人员都不要去了解,只要知道想要修改区块的数据非常的难,因为中本聪设计的非常巧妙,想要修改块的内容,要将从此块之后所有的内容全部进行修改。

  至于如何做是如何做到的,防止被修改,我在下一节的算法中会详细介绍。

  (区块链数据结构还有NextHash没有在图上画出来)

  看到这个表结构,如果你产生一个疑问,链条总归要有开始吧?这个问题非常好,我开始也产生过这个问题。中本聪的解决方案是在程序内部内置了一个创世块,中本聪本人就是创造比特币的上帝,然后启动后只要还有一台计算机在运行这个程序,块的生成就不会结束。

  还有另一个分布式数据保存特性,也让修改数据变得几乎不可能,因为这个数据不光存在某一个人的机器上的,保存在很多台的机器上,这个应该成为了比特币故事最大的亮点。

  但其实物极必反,在选择了开放和安全外,必然牺牲效率。因为在比特币里面不能直接查询余额的,你只能顺着链条从头开始查找所有交易记录,然后再进行加减计算,得到你当前的余额,这就让比特币的效率不可能高。

  只要知道区块ID,很多网站都是可以查对应区块的信息的,因为数据是公开的吗。具体我查了一下,btc.com这个矿池其中一个ID的余额,不少有1534呢。

  https://blockchain.info/address/1C1mCxRukix1KfegAY5zQQJV7samAciZpv

  1.4 基于区块链的文本编辑器

  这里用一个比喻就能讲明白这个结构的特点了,好比A君用Word在写一份文档,每输入的一个字都要同步给P2P网络上的所有结点,增加也好删除也好都要上传,然后文章的最终稿是不直接保存的,就相当不能直接查询余额。要得到A君的文章也很简单,把A君所有的操作全部找出来执行一次就是最终的结果了。

  网络上当然同时也有B君,C君在输入,还是那个链式结构,按先后顺序按:谁操作 + 操作内容,依次首尾相连串好。如果你想做区块链创业,用这个区块链的文本编辑器写个计划书,制作一个区块链编辑器,将作者的写作过程全程记录,说不定也能搞到融资,各位随意拿走不用算我发明。

  当然比特币的区块链是虚拟币交易,显然不能是个人单独行为,得按交易的形式出现,理解也简单,就是被执行的主体是多个对象,按交易规则来进行就可以,这个我放到交易里面来详细说明。

  那区块链是如何保证安全的呢?这就要看下一小节的算法部分。

  1.5 算法

  用到的算法也没有特别高深的算法,就二个算法:椭圆曲线加密算法和哈希算法。这二个算法一直在互联网上被广泛使用,几乎所有的语言都有函数库都有。

  二种算法的原理网上非常多,这里只介绍作用,第一种非对称加密,这个算法有下面这种能力。

  公开公钥(Public Key),自己保存私钥(Private Key),只有私钥加密过的内容才能被公钥打开。

  用普通话打个形象的比喻,我给你一把钥匙,然后让你开锁,这把钥匙能打开的锁就是我造出来的,而且只有我才能造出来。和我们平时的生活习惯有点不一样对,这个算法的学名叫:椭圆曲线加密算法。

  在区块链里面,公钥字符串就是比特币帐户,长这个样子(Base58编码过):1C1mCxRukix1KfegAY5zQQJV7samAciZpv 。

  还有另一个叫哈希算法,这个算法有三个特性:

  1、输入的值差别很小,但输出却完全不一样。

  2、不管输入多少位,输出的位置能固定。

  3、知道输出,很难还原输入。(有中国数学家曾经研究过如何求解输入,但256位的计算量太大)

  有个网站可以试:Lhttps://www.md5hashgenerator.com/ 。比如我MikeZhou和MikeZhou1只差一个数字,但结果完全不同。大家可以上这个网站自己尝试。

  MD5(MikeZhou)=cb19e9b0b3cb8a8e5126677dbe1dbad5

  MD5(MikZhou1)=48cc0cd823192ea7bd0aa5f1e60cfdf0

  MD5是Hash算法一种,而比特币用了Double-Hash,就是连续二次SHA的哈希(叫 SHA256d),就是要防止暴力破解求解输入。

  好了,有了数据结构和算法的基本,我们就很容易讲清楚挖矿的过程。

  1.6 挖矿过程

  挖矿其实就是一直在做非常无聊但很有难度的事情,这是中本聪精通博弈论的地方了,这个设计让比特币几乎可以永远的活下去。

  挖矿其实就是大家事先约定的一个猜迷游戏。谜底规则大家事先约定,就是不停的试一串特殊的Hash值,加入的计算的人越多,就就越特殊越难找到。

  这里我们要知道的就是:

  1、规则大家都知道。

  2、谁也不能提前开始,大家开始时间一致。

  3、没有投机取巧的办法,只能硬算。

  4、赢者通吃。

  然后就是比谁算的快还有运气好,然后谁先算出来,直接广播给所有的结点,所有结点一验算符合规则,就不再算这一块的了。

  赢的ID将得到:

  1、系统约定好的奖励的特定数量比特币(最开始是50,目前是12.5,每4年减半);

  2、所有在交易内的交易费用。

  与之相应的义务:

  1、负责写入生成的当前块。按比特币的规则约定,先算出来的人才能发起写入指令。

  因为有交易费用存在,所以矿工们肯定要按正常规则来操作,因为错误的东西本身不会被其它结点执行,而且还白白损失交易费用的。

  中本聪在这一块的设计可以堪称是天才设计,当挖的人多了的时候,计算难度就会自动加大,对比下面的图一张2009年的,还有一张是今年的,你发现差了好多个0,对这就是难度增加导致。因为上帝当年设计的规则是,要让SHA256d(时间,上一块Hash,随机数)的结果要符合规定个0开头才行,如果说生成的数字是随机的。

  概率 = (1/16) ^ N 【其中N = 要求0的个数】

  2009年的数据是8个0

  2018年2月的数据是18个0

  那么现在挖矿的难度是当年比特币新出来的时候约1,099,511,627,776倍,当然这里面有技术进步的因素,从CPU到GPU,再到FPGA,到现在的ASIC,ASIC也不断从60nm到现在的14nm,越来越快。

  而这也是比特币一直被诟病的地方,空转消耗大量的电力,1800万Th/s,按现在最新型的机器矿机规格:消耗2度电/小时产生13.5Th/s算力来算。

  年耗电量 = 1800万 / 13.5 * 2 千瓦时/小时 * 24 小时 * 365天 = 233.6 亿度。

  而且我是按最新的节能型的机器计算的,还没有计算机房制冷消耗,所以整个电力算下来,基本相当半个三峡的发电量。

  下面是一张总体的算力图,一直在增加,这也从侧面说明在当前比特币价值情况下,矿工的经济收益为正,矿机之前卖脱销也是因为这个原因导致。

  当然大家知道赢者通吃的规则后,那么这样的话,大家的收益不就是波动很大吗?有人投入了几千万在这里面,为了投资回报的稳定,所以就是矿池的产生,就是大家组团来挖,挖好了按一个约定好的规则来分币。

  下面就是一个算力的分布图,可以看出前3家的占比超过60%了。

  1.7 交易过程

  这里单纯以比特币的交易来说明区块链的交易过程,不涉及商业上的交易(钱的交换)。

  比特币的交易,有了上面数据结果和算法基本就非常安全了。链表结构和算法就是构建一个受大家共同监督安全的不可逆的数据流,基本如下图所示,小k到大K椭圆加密不可逆,大K到A的SHA256d的也不可逆,双重保证,基本在现有的计算机构架下是破解是不可能的。

  就算哪天有一个矿池拥有了51%的算力资源,最多有可能垄断挖矿的权利(这是有可能的,后面经济分析详细说明),不可能来任意修改数据,这样就完全不是比特币了,失去了最初的意义,也就会变成一文不值。

  当然为了进一步安全,中本聪在设计之初还制订了很多其它细的规则,比如:

  1、矿工刚挖出来的矿是不能马上交易,因为离当前块越远的数据越安全。

  2、利用交易费来调节,优先早生成和交易的比特币交易。

  有了上面的基础那么交易过程就变得非常简单,交易中有以下参与方:

  1、刚才猜出谜底的矿工:负责校验交易和写入交易,并收取交易费。

  2、其它分步式结点:负责同步和确认交易正确性。

  3、出售方:提供自己的私钥加密的数据,用私钥就证明了是拥有方发起的交易。

  4、接受方:产生和自己关联的收入交易记录。

  归根结底,这么多操作就是往区块中填入数据,不涉及任何商品和钱的交易,货币交易是区块链在虚拟货币交易所的衍生交易。暂且记住这个结论,后面经济分析时使用。

  比特的区块链交易 ≠ 货币交易

  当然实际的流程控制比这个复杂,因为比特币过于火爆,而开放的分布式天然并发又不够。所以矿工们研发了交易池,算是BIP计划的一部分吧。相当去医院看病,医生数量有限,病人多,大家先全在大厅等着,然后医院结合看病时长和给的诊疗费来计算先给谁看。

  这里比喻的看病时长,交易费由交易方在交易前自己输入,交易“称重公式

  = 148 * number_of_inputs + 34 * number_of_outputs + 10

  1.8 比特币钱包

  有了上面的介绍,一句话就能讲清楚比特币钱包,其实就是上面算法里面讲的那个公钥,所以钱包这个概念在区块链中并不单独存在,而是保存在一条条的交易记录里面。

  因为都是一些没有任何意义的数字,大家使用起来比较麻烦,于是就诞生了很多比特币钱包管理程序,但这里有一个安全隐患,如果你自己不知道如何在自己本地生成钱包,而是利用网站去生成公私钥,理论上网站都有可能把你的私钥保存一份,当你帐户(通过公钥直接查找,数据公开的)有比较多钱的时候,要面临怎样的风险谁也不知道。

  当然只输入公钥在钱包程序里,是没有安全隐患的,可以很方便查找自己的交易记录和余额。

  一言以蔽之,比特币钱包是人们虚拟出来的一个词,在区块数据中其实就是公钥。而很多钱包程序就是为了方便一些没有技术能力的人,让他们方便的进行虚拟货币的交易。

  但这里真的给一些正在大额投资虚拟货币的人提个醒,如果不是自己本地生成的公私钥,还真的要当一万个心。私钥的保存非常重要,真要丢了,可不是打个客服电话就能要回来的,它就真的永远消失了。

  1.9 P2P网络技术

  这个就是大家以前用过的BT和VeryCD电驴下载,用的技术是一样的。这个技术就是实现去中心化的网络传输算法,我把网络交换部分也称之为算法。

  所以,我们发现区块链的关键技术是十几年前就流行过的技术,如果真是什么颠覆性的技术,不会雪藏这么久不出招的。

  1.10 金融应用

  我2017年就深入调查过区块链技术,主要是看看对我们金融行业有没有一些新的启发,调查完发现没有什么作用后就搁置在一边了。今天看到身边好多朋友都想去炒把币,所以出来写这个文章。

  为什么说没有用呢?

  信任问题:通过电子合同解决了。金融行业用CFCA认证过的合同是有法律效应,而且也做到了不可篡改。

  合规问题:只要企业能提供借款人的按法律要求的一些证明文件,事先收集保存到时候提供就可以,一些影相文件和签字文件,这个用不用区块链存不关键。

  借款数据:法院不看企业提供的数据作为证明关键的数据,都是以银行提供的流水为准确,A是不是从企业借款,是看银行是不是有打款记录,不看企业数据库或区块链中保存的数据的。

  因为合同不可篡改,又有银行流水记录,证据非常完善,至于去中心化,那更是完全搭不上边,哪有我们公司的数据完全对外公开的道理。

  1.11 技术总结

  区块链其实并不是用了什么新的技术,但将已有的一些技术进行组合,给人们一种全新的用技术来实现一个安全和互信的产品,加上恰逢金融危机后推出,运气不错,所以有了今天的地位。

  但光了解技术,还是不足于让我们明白中本聪设计区块链的初衷。我们应该去了解创造区块链背后的极客们的哲学思想,这样就不至于去犯拿着锤子到处找钉子的错误。

  02 技术极客的自由乌托邦

  这一节将尝试从哲学层面来分析,创造比特币的技术极客们,如何用自己擅长的技术领域,按他们的世界观和价值观构建出一个虚拟世界。

  2.1 新时代的乌托邦

  欧洲历史是就出现过多次乌托邦思潮,提倡无政府主义,现在同样还有人保有这种思想,但遗憾的是目前也有一些小岛是无政府状态,但基本是过着在原始人的生活。

  而区块链最大的特性就是去中心化和开放,这给人一种自由的享受,并且用一系列的技术手段在开放的同时还保证了安全。这就等于构建了一个开放自由并且还保护私有产权的新互联网模式,难怪这会让一些大人物们欢呼区块链的时代的到来,而中本聪把第一块命名为创世块,也表明也自己希望成为新时代的上帝。

  2.2 自由的基因

  自由人文主义在西方经历了几百年,从圣奥古斯丁思想提出,到现在成为欧美等国家的主要哲学思想。以致于丹尼尔·汉南最近写的《自由的基因》里面说自由是盎格鲁圈的基因。

  当看到这个新的去中心化的区块链技术出来以后,又让一些人内心持有自由主义观念的人,终于看到一个完全无政府(去中心化)的乌托邦社会(比特币)的诞生和崛起。这其实非常符合一些出生在中国,受美国教育以及长期生活在美国的名人的价值观。比如:大科学家张首晟、硅谷投资人吴军等,他们觉得这是互联网的分水岭来临。

  他们当然是我非常尊重的人,在自己的专业领域有非凡的成就,是我不能比的。但就区块链技术的研究,未必有我深入,至少我相信他们没有时间去Github上下载过C++的区块链源码来看。但之所以最说区块链被这些专家夸大了,不是因为我看了源码,而是因为我还做过一些哲学上的分析。

  2.3 自由主义的哲学发展

  就算我们从哲学的历史来一步步推导,绝对的自由最后就是必然产生强权,而从现在的比特币来看,也是一样的,算力最强的拥有交易写入权,最后受益方一定是那些强制的一方。

  我画了一张自由的哲学发展史,从笛卡尔提出我思故我在,把人从上帝的附庸中提拔出来以后,到最后黑格尔的强权即公理,到最后尼采的强者逻辑直接给希特勒屠杀犹太人找到了理由。而在受黑格尔和尼采的思想影响下,也直接导致德国发动二次世界大战。

  反观二战后,美国的就是用马歇尔的政策,用的是老子的思想“夫唯不争,故天下莫能与之争”,主动牺牲自己利益,扶持欧洲和日韩的发展,当这些国家发展了反过来又进一步促进了美国的发展,才有了今天美国霸主的地位。

  讲这些哲学逻辑就是想说明一个道理,绝对的自由产生强者权利。完全的去中心化,大家完全按既定规则的投票(比特币现在逻辑),拿区块链最火应用虚拟货币来说,最后就会形成几大矿池,几大交易所,他们就是虚拟货币领域的无形的希特勒,决定着各种BIP(比特币改进计划)向他们有利的一方游走,而小散投资者们就是他们的韭菜。

  如果认为这种完全不受政府监管,最后都是强者恒强的形式是互联网的未来,那可能我们就得同意张首晟所说的目前形式的区块链条是互联网分岔。

  2.4 除虚拟币货并无大的区块链应用

  再从结果来看,这么重大的技术,区块链至少被这些专家讲了5年以上了。我们现在除了看到大家在热火朝天在炒币以外,身边没有看到任何一个大型的应用是用区块链实现的。

  如果真是一个革命性的任务,我想Google,Facebook和BAT公司怎么可能这么多年还没有具体的应用呢?

  如果您刚才认真看完了技术篇幅的加构,便知道区块链不过是:P2P网络 + 链表 + 二种通用加密算法,这几样东西的组合,完全不足于颠覆现有互联网,现在很多大公司不用不是因为不知道和不了解。而是因为现实在有更好的技术,比如分布式关系型数据库(如Mysql),分布式缓存,分布式消息队列和分布式文件存储等。

  不管怎么改进区块链技术,都是不可能实现几亿用户20万/秒的交易记录的(支付宝2017双11的记录)。

  这些技术本身都是分布式的,部署在不同机器上,但同时又实现了中心化的管理,这里面技术难度要远远大于区块链的技术难度。

  当然还有其它一些利益相关的区块链的支持者,我就一个观点,如果他鼓吹的东西对自身利益有非常重大的关系,不管他讲的如何真诚都可以忽略。非常简单的道理,若真是好东西,会公开的告诉你吗?

  所以像李X来,薛XX等,比如从事区块链创业圈的人,都不算是区块链支持者,应该说是虚拟货币的支持者,其目的就不用我来告诉大家了。

  2.5 技术现状

  想想比特币到今天,绝对超出中本聪当初建设他的目的,每天消耗大量的能源,让其成为人类新时代的“郁金香”。

  03 新时代“郁金香”

  这一节从社会学角度来简单分析虚拟货币的现象。

  3.1 想象共同体

  前文提到了虚拟货币是新时代的“郁金香”,这是经过自己的一些分析的。就像赫拉利在《人类简史》中提到智人最大的进步来自7万年前的一些基础突变,让人具有了讲故事了能力。这样大家不断的通过讲故事,就形成了共同的社会习俗,形成了各自的文化和社会关系。

  如今的比特币不就是完全是大家的一个想象共同体吗?想象共同体有没有意义?当然有意义,国家和民族不都是想象的共同体吗?这个共同体的意义就要看其给我们实际带来了哪些价值。国家和民族给我们带来什么价值,就不用过多的阐述。

  那么比特币和交易带来了什么现实的意义吗?直接替代现有的支付宝,这是一种舍近求远的行为。目前的用虚拟货币来实现的支付都是要转换成美元或其它法定货币来支付给商家的,这不说等于饶了一个圈子吗?

  虚拟货币也好,实际货币的价值也好,一个很重要的作用就是交换和流通的。

  3.2 虚拟货币价值

  虚拟货币中最大的一家比特币,最后还是要通过银行卡来进行交易,但价格波动太剧烈。虽然有一些技术型公司愿意接受比特币作为支付手段,但卖的肯定是虚拟产品,比如Steam和一些游戏公司,这些公司虚拟对虚拟还是挺对路的,反正公司不会亏。

  但凡是有成本的交易,比如苹果公司卖手机,试试用比特币结算看看,价格一波动,到时候连供应商的货款都付不出。

  还有一个最大的问题,安全性完全没有保障。就拿个人来说,试想你把你所有的钱全换成比特币,你每天睡觉都提心掉胆,放电脑存着吧怕被盗,抄本本上吧怕丢,记吧还又记不住。

  如果一家公司呢?所有资产就是一串完全没有保障的数字,谁保管着私钥马上人间蒸发。

  当然支付者们可以讲,可以不断改进吗?对是可改进。但要做到安全稳定不波动,不就是等于重新把现代金融体系重新在虚拟世界重构一次吗?最后不就又演变成现代的金融制度吗?

  所以我才会说想通过区块链技术来构建一个自由的金融社会是一种乌托邦的设想罢了。

  这就很容易得出结论,数字货币不过就是一个没有实际价值的“想象共同体”,和当年的荷兰“郁金香”最大的区别是当年“郁金香”只在荷兰流行。但今天虚拟币货通过更新的技术和更强的传播手段,传播到了全世界,所以这一波应该会涨得更高更持久一些,但泡沫终归还是要破灭的。

  04 谁是赢家

  这一节就要尝试回答,在当前的区块链大环境下,哪些人是受益方。

  区块链的生态圈包括哪些角色?

  虚拟货币会发展成为支付宝那样的货币吗?

  挖矿的经济价值如何?

  

  4.1 区块链的生态圈

  我们来看看区块链生态圈有哪些角色,我们就只罗列直接关系者,背后的供应链不在一一列举了。

  炒币者

  早期进行的一些人应该有不少赚钱了,但小散们不可能赚太多,后面我分析原因,现在进去的基本都是韭菜。

  矿工

  投资者,存在一定风险,但追求的是稳定的回报。

  矿机供应商

  目前各种矿机供不应求,应该是这波区块链的受益者。

  矿池所有者

  大的矿池所有者,挖矿得到的交易费是不分成的,所以应该是较大的受益者。

  虚拟货币交易所

  食物链的顶端,收割者,不要任何金融牌照,上一个新币就收几千万,反正人傻钱多,不管上什么都有人买,不怕没韭菜。

  技术开发者

  赚口饭钱,干什么不是干,不过干了区块链,工资能比其它人高点。

  虚拟货币发行者

  早期的发行者,早已身价不可估量。如今也是赚个微利,还有可能赚的钱不够付交易所的上币费。

  区块链创业者(除虚拟货币从业者以外)

  我非常崇拜的一群人,虽然大部分人是拿锤子在到处找钉子,但是有情怀,说不定会找到一些新的业务模式,但应该不是什么颠覆性的。

  4.2 矿池的正经济利益

  我本来还想自己统计,结果有人做了一个网站,专门显示各种挖矿的经济利益。网址在这里:https://www.coinwarz.com/cryptocurrency/

  能看出来挖比特币不是目前经济价值最高的,现在要挖莱特币。对不起,比特币矿机和莱特币矿机不同,不能说不挖比特币去挖莱特币,当然这个里面受实际价格的影响,但总体来说是赚钱的,但请注意这是对于大的矿池和大的矿厂。

  由于比特币去年的快速上涨,而矿机的供应有点落后,但随着价格的回落和矿机的供应到位,这个市场的经济利润马上会归于零。

  4.3 投资矿机价值

  对于交易所和大矿池的拥有者,当然毫无疑问,他们会想方设法自己或者买通其它人发出各种虚拟货币才是未来的新经济,区块链会颠覆现有互联网这样的言论。

  对于很多小散投资者,可能买个几台几十台矿机放家里,然后再自己顺便炒一炒,想着自己的发财梦,我先从经济规律上来分析小矿工们赚不到钱的道理。

  学过经济学的都应该知道下面的成本曲线,当 R(收入)=ATC,大家不再买新的矿机,当R(收入)< AVC (电费+人工费+其它运营费用)。

  根据经济规率:只要经济利润为正,就会不断的有新加入者,直到最后经济利润为零,但不同的矿工由于成收入和成本各不相同,当矿池们为零的时候小矿主们可就早就变成负的了。

  作出上面的判断,主要有由于下列原因:

  1、小矿工的规模化原因,矿机的运行效率肯定不如大矿厂,这样R收入会低。

  2、小矿工采购批量小,平均固定成本会高于大矿厂。

  3、小矿工电力平均成本和运营成本可能都会高于大矿厂。

  4、小矿工无法得到交易手续费分成(目前是这样)。

  基于以上分析,可以得出结论:投资了小规模的矿机最终会因为规模效应亏损。当然如果运气好遇到比特币一起涨,那这样也别折腾,直接买不就好了吗?

  那我就再来分析下直接投资的价值。

  4.4 小散投资虚拟货币的价值

  首先,有一件事实必须承认,虚拟货币本身是一段数据,数据被加密来加密去存在多少块硬盘上,除了被炒来炒去,用来真实商品交易非常少,而且使用起来也非常麻烦,可以说本身不创造任何价值(当然不是说货币不产生价值,货币最直接的价值就是降低交易成本,而比特币却不是)。再次强调,不创造价值不代表没有价值,只要人们认为他有价值他就能卖得了。正是因为这个原因,现在各种虚拟货币才这么火。

  用下面的图来形像的说明吧,比特币的钱都来自投资者的投入,那么投入的可能是在这的高度,除了付给发行者收益,交易所收的手续费还有矿工的成本,那么进入的钱,等出来时可能只剩一半了。

  以最近24小时比特币的数据来说,24小时的交易量是20亿美金,算1%的交易费(交易所直接收的现金)。再以1万美金/BTC来计算,每天挖出还有矿再加上收走的比特币交易费,共计2000个比特币左右。当这二项的收费就4000万美金/天,再加上被那些创始人赚走的,每天至少在5000万美金以上的净支出。

  这就相当投一块钱进去,5毛钱出来,然后我们还想信我在这个市场能赚大钱。

  这里有一个概念一定要搞清楚,这里无关比特币涨跌,比特币的量是按其规则运行不会变化。但因为比特币不创造价值,而法定货币的平衡和币的涨跌是没有关系的,相差5000万一天这是一个实际货币上的平衡。而这个市场又有人不断的在抽取价值,那么就要靠不断的更多的投资加入才能维持市场的繁荣。

  4.5 如何解释那些财富自由的人

  有一些,极少数没错,通过虚拟货币实现财富自由的人,想想2009年如果花5000块买比特币,现在身价几个亿美金了,怎么能说投资没有价值呢,这是屌丝逆袭的最好时机了。

  我只想说一句,真小散在5000买的时候,涨到1万的时候基本就卖了。如果在10万的时候还没卖,一定是忘记自己买过比特币了,但对于小散5000块的投资不太会忘记。如果到了50万还没卖,基本上是忘记了密码。所以不要做这种不可证伪的假设。

  当然大家可以指出大量QQ群,朋友的朋友,赚了几千万几个亿的。我只能说要真是一个普通人赚了几个亿的人,是不会在Q群里发言,发朋友圈的。最有可能是默默的删除原来屌丝好友,生怕他们来找自己借钱。所以这种消息听听也就罢了,自己赚了还是亏了自己心里还不清楚吗?

  我想信那些1万多美刀进场的人,最近能感觉到一丝丝的寒意了。只是我们听多了那些一夜暴富的人,却忘记了还有更多一贫如洗的人。

  4.6 比特币数量可控吗?

  最后再拆一根支撑小散炒币的沉重梁,就拿最值钱的比特币来说,比特币数据最终固定在2100万个,不增也不减,最终一定会涨上去的。

  好,确实区块链下修改数据是几乎不可能,但不代表不会增加。复制还是可以的,大家知道BitCoin Cash吗?一群矿工不满足1M大小的区块,要修改为8M,自己就把原来的比特币数据拷一份,命名为比特币现金(BitCoin Cash),原来的比特币帐户密码在比特币现金里面也能用。

  你敢相信,就这样1个变2个了,不是说不能增加的吗?而且价格之前也到2000多美金了,就硬生生的多出200多亿的市值出来。如果想了解细节,可以去百度比特币分叉,什么分叉,就是硬拷贝好不。

  拿阿里巴巴股票市场为例吧,把谁在这个时刻持有阿里巴巴股票的数据记录下来,然后直接拷一份叫阿里妈妈,继续明天挂在交易所里排一起交易,体验到了“强权”的味道了吗?

  反正看上去没有人有损失,原来持有阿里巴巴的在阿里妈妈里多了一份,没有任何人受到了损失,这就是完全没有监管的自由金融市场的样子。

  就算不分叉,来看看全貌,一共93种在市场上交易的货币,现在找交易所上个新虚拟货币。新货币都号称解决了比特币的这问题和那问题,还有排第二的莱特币号称可以编程,是一个平台,是所有虚拟货币的代币,玩法层出不穷,连排最近一名的总市场也在500万美金以上。

  我看了几种主流的虚拟货币的技术架构,都基本还是没有脱离比特币的区块链技术框架和思路,不过是在效率上更高一些,号称加了更多的一些功能。

  可以在https://blockexplorer.com/market查看。

  列举了这么多,你还相信区块链下的虚拟货币神话吗?一个故事可以讲一段时间,但要讲长久,关键还是要看创造什么样的价值。

  所以,我非常赞成政府对比特币的严格管控,真的是在保护我们普通投资者。

  最后、引用老子的一句话:“天之道,损有馀而补不足。人之道,则不然,损不足以奉有馀。”,投资市场就是这么一个“损不足以奉有馀”,所以小散投资者们就是虽然钱少,但还是用来损的,去补那些大的玩家(矿池主,交易市场主人)。

  4.7 投资者心态

  但我知道,就像当年的3M一样,只要政府不出手,一直让他开着,总归一直会有人加入的,所以我还是相当支持国家来严控虚拟货币交易的,至少能挡住一部分人吧。

  从数据角度讲,你只要承认虚拟货币不创造价值,进行1块钱,被分走5毛,然后还要博取100倍、1000倍的收益。只要你认为自己掌握的信息、自己的能力和自己的运气和别人一样(实际是这个市场还存在操控),根据正态分布原理:想通过投资虚拟货币得到巨大收益的可能性,就和自己手机上安装一个挖矿程序想挖出比特币一样的低。

  造成这种现象的原因很简单,身边总是留传着某某个人因为炒币财富自由了,这种事情我一天都听到3回了,这种快速赚钱的故事最能相互间快速传播。但仔细想一想,这种进一块出五毛的市场如果大家都赚钱了,韭菜在哪里?歪国人都是韭菜?

  当然我知道很多投资者还是会加入炒币,因为

  1、用点自己的小钱、比如投入自己财产的10%(一毛钱都不应该送进去)。

  2、不懂跟风、博取财富自由(参照我上面的概率分析)。

  3、没什么好的理财项目(那就放货基,把精力放在提升自己上)。

  如果是上面几种人,我建议有这钱不如陪家人出去旅游一趟,但如果是下面的情况,我就不劝阻了,祝君早日财富自由。

  1、我相信在炒币这件事情上,我的能力比别人强。

  2、我相信我有某种神奇的能力,炒币总能低买高卖。

  3、我相信我的运气总比别人好。

  2、我认识带头大哥,他有内幕消息。

  3、我相信身边就有大量通过炒币致富的案例。

  有时候我也一直想不通,乐视复盘的第一天,就有不少人在跌停的时候买入乐视,因为绝大部分人肯定认为在5个以上跌停板,但总有一些人对自己特别自信在第一天进入。我反正还是没特别想通,如果你们有答案可以留言告诉我。

  05 总结

  第一次在公众号写这个万字长文,也算结合自己的专业和去年学习的知识,从多个维度来分析区块链技术。观点未必正确,所以欢迎留言讨论,但有一点我非常肯定,小散们远离虚拟货币为妙。

  另外我接下来还会补充二篇内容来说明:

  1、微信的朋友圈也可算是区块链的应用。

  2、大部分现有的区块链创业都是在拿锤子找钉子,很多目前用区块链创业项目用中心化的技术方案实现起来更好,用区块链实现就是蹭热点,为了拿融资方便。

  最后看到这里的朋友都不容易,非常感谢大家的支持,如果有兴趣或者不同意见,欢迎留言讨论。

  引用站点和图片

  [1] 比特币数据结构图片来源 https://www.researchgate.net/figure/a-Blockchain-structure-b-Smart-contract-structure_309543764

  [2] 比特币区块数据查询 https://blockchain.info/

  [3] 比特币交易费用介绍 http://bitcoinfees.com/

  [4] 挖矿收益查询 https://www.coinwarz.com/cryptocurrency/

  [5] 比特币市场价值查看 https://blockexplorer.com/market

  [6] Satoshi Nakamoto, Bitcoin: A Peer-to-Peer Electronic Cash System

  [7] Andreas M.Antolopolutos, Mastering Bitcoin


来自:

https://new.qq.com/omn/20180203/20180203G04168.html


posted @ 2019-10-23 09:14 狼爱上狸 阅读(13) | 评论 (0)编辑 收藏

再抛砖:基于区块链的去中心化存储终将失败

最近看了很多区块链上的去中心化存储方案,各种方法不一而足,但是仔细看了各种方法,实话说我的个人结论是“基于区块链的去中心化存储终将失败”。

存储的第一要素是可靠性而不是价格

在存储市场,可靠性有时候也称之为持久性,主要是指在文件存储以后,有多大可能性文件被无损地获取回来。

这个道理是不辩自明的,没有人存储数据是可以不考虑可靠性的,但是在大多数去中心化存储方案的白皮书中却是没有可靠性指标的,大多数都是通过含糊其辞的我们在全网备份来保证文件不被丢失。这够了么?请移步 https://aws.amazon.com/cn/s3/ 看看商业的存储服务是怎么定义文件持久性的。

从系统设计角度来说,可靠性设计是设计里面难度最大的工作。在一年 365 天的每一天都能够正确地读取数据,但是再最后一分钟数据没有读取到数据,那么可靠性仅是 99.98%,这个数字看起来很高,但是从可靠性角度来说是不够的。原因很简单,从最终用户角度来说,最后一分钟获取数据的失败,实际上意味着整年工作的失败,我存一年这个数据,也许仅是为了读这么一次,你这次给不了我数据,那你这一年的存储是第一天就丢掉数据了,还是在我获取的那一分钟前一秒丢掉数据,对我来说没有任何区别。
我们自己电脑里面使用的硬盘提供的存储,某种意义上也是一个相对低可靠性的存储服务,大多数人都能相信把数据、文件存到硬盘上,在大多数情况下数据并不会丢失,稍微懂点技术的明白建一个 Raid0,这个文件丢失的可能性已经是微乎其微了;比较去中心的存储服务,也许价格上是比传统云服务公司提供的存储服务便宜很多,但是如果和个人购买一个硬盘甚至构建一个 Raid0 对比,这个价格优势就不存在了。

去中心化存储的可靠性问题比想象的大

如前文所说,去中心化存储方案的白皮书中是没有提供可靠性指标数据的,在我看来,很悲哀的现实是所有的去中心化存储方案因为他的分布式是无法给出一个可靠性指标数据,这个在传统企业存储市场业务上已经是个很大的劣势,但是也许有人会认为虽然他们给不出具体的可靠性数据,实际上可靠性还是很高的,因为去中心化存储会通过全网的备份,将同一个文件放到不同的节点上来提高数据的可靠性。

这个听起来没错,但是如果我们深究去中心化存储的实现方式,我们会发现其实不然,这主要在于去中心化存储在进行文件存储时的切块存储模式,为了保证文件的安全性,也就是文件不能被矿工访问,主流的去中心化存储方案都会对文件进行切块,然后将不同的块存储到不同的节点上去,这样所有的存储节点都不拥有这个文件的全部块,文件属主就不用担心文件本身被非法获取。

这样的存储模型确实能够解决文件安全性的问题,但是反过来却造成了文件存储可靠性的进一步下降,原因很简单,如果一个文件被拆分成了 100 个块,这 100 个块会被分散存储,那么只要有任何一个块失效,这个文件本身也就失效了,分块操作大大降低了整体文件的可靠性,在 100 个块的情况下,失效率实际上是提高了100倍。

矿工或者说节点的行为并不能改变什么

实际上大多数去中心化存储方案也都关注了可靠性的问题,提出了一些方法来约束矿工的行为,比如 FileCoin 提出了 Proof-Of-Spacetime , Proof-Of-Replciation 一堆复杂地概念,寄希望于用这些指标来经济驱动矿工可靠地保存文件,但是在我看来这些方法某种意义上是所谓地缘木求鱼。

首先我认为,在大多数情况下,只要存在一定地经济激励,节点管理人的行为并不会是造成文件丢失地主要因素,某种意义上他们事实上不会有兴趣去管理这些存储地碎块文件。对于去中心化存储的节点来说,所有的储存在他电脑上的文件都是毫无意义的二进制字节,而维持这些字节的存在是会给他们带来一定的收入,正常情况下他们不会有什么欲望去删掉这些东西。因此通过进一步强化经济激励,来保证他们不去删除这些对他们无意义的字节流,意义并不大。

真正影响文件存储可靠性的,主要来自于两个因素:

  1. 硬盘的可靠性。按照我在网上搜到的硬盘可靠性分析文章,一般性机械硬盘的年失效性中位数大致是 3%,那么换言之每 30 块硬盘在运行一年以后会坏 1 块,不精确的概率计算,如果有 200 块硬盘,一年运行下来有 6-7 块损坏,那么假设一个 200 个节点的网络,每个文件被拆分成 100 块,每个块在全网分别形成2个复制,那么 1 年以后正常可以期望 3-4 个块的损坏,能够拿回完整文件的可能性微乎其微。
  2. 节点管理人对于节点的管理水平:传统的 IT 技术上,针对这种硬盘可靠性实际上是有整套的解决方案,RAID 系列就是专门定义了解决这种问题的,比如简单搭个 Raid0,就可以将出错可能性降低到 3% 的平方,也就是说 0.09%,但是作为去中心化存储节点的提供者,他们架设节点的目的是本来就是用简单的闲置硬盘空间来换取一定的经济激励,提供的容量空间直接影响他们的收益。所以如果有构建 Raid0 的两块硬盘,肯定是将两块硬盘分别使用,而不会是构建 低容量的Raid0 阵列,而且如果希望拥有大量的去中心化存储的节点,那么客观上能够组建 Raid 阵列的节点管理人只是少数。

复杂的计费模型是去中心化存储的最后挽歌

计费模型的复杂性也是去中心化存储方案的一个重大问题,这实际上是来源于存储需求人和存储提供者对于存储需求理解的不一致,而作为去中心化存储方案必须通过技术来弥合这个不一致。让我们看下双方是怎么看待这个存储需求:

存储需求人的需求:我今天把这个文件存到你这,也许明年才要用一次,我明年用的时候你将这个文件完整地提供给我,我就付整年的钱,否则,我希望你交罚款。

存储提供者的需求:我同意你将这个文件存在我的本地硬盘上,每存一段时间,你就给我钱,如果你不付钱,我就希望把这个文件删了把空间腾出来给其它愿意付费的文件。

这样的计费模型实际上是很复杂的,如果再加上文件本身的分块操作,情况会变成存储需求人愿意付款的前提是所有的存储提供者都正确地返回了所要求存储的文件块,想象一下 100 个块只返回了 99 个块的情况,因为这 100 个块的存储服务来源于完全不同的经济实体,达成这个共识的复杂度真不是程序能够轻易完成的,一个简单的规则是能完成分配,但势必伤害到其中某一方,然后造成这一方的离开。当双方需求都是合理的情况下,伤害任一方都不合理。

用户画像的缺失也是去中心化存储的问题之一

这个就不展开讲了,简单说个结论,是这些去中心化存储方案根本没说清楚或者说没去想谁会用他的去中心化存储。

随便抛转,还是希望抛砖引玉,大家给点指正,帮我理解清楚一下这繁杂的方案背后的东西。


来自:

https://ethfans.org/posts/decentralized-storage-will-fail

posted @ 2019-10-23 09:12 狼爱上狸 阅读(13) | 评论 (0)编辑 收藏

Cannot find module 'crypto-js’

移植了老师的代码,出现了该问题,应该是js加密的问题,而本机中并没有使用过js加密,所以并没有该包的原因,遵循没有就安装的方式进行解决。

1.直接安装该包,网上大多数都是这个方法

命令行代码如下:npm install crypto-js

跟我上一篇文章出现的问题一样,npm需要安装的话由于要连接外网,99%的国内电脑肯定还是不行的,还是做国内资源映射

2.做国内资源映射

命令行代码如下:npm install -g cnpm --registry=https://registry.npm.taobao.org

这一步如果在之前做过则不需要,会记住映射的url

3.在命令行输入跟第一步差不多的方法

命令行代码如下:cnpm install crypto-js

在ionic开发中,需要typescript和nodejs的开发环境,其中很大部分在一开始安装了,但是如果要做更新或者下载一下需要的包的情况下就仍然需要做映射,才能正确安装新的环境。

感谢淘宝为开发者做的贡献。
————————————————
版权声明:本文为CSDN博主「是阿晋啊」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_38255285/article/details/82793231

posted @ 2019-10-19 11:23 狼爱上狸 阅读(9) | 评论 (0)编辑 收藏

峨眉山

1、四天时间爬峨眉山足够,可以做到全山徒步环线,景点全扫光
2、吃的住的不算贵、至少在全国知名景区来说很不算贵。想节约的话,一个房间不超过200元的从山脚到高山区的雷洞坪都有。吃的虽然比山下贵,但是也在可以接受的范围。一个人节约点吃,几十元一天不会饿到你的。
3、按照4天环线给你设计:你没说从哪里出发?只能大概给你按照成都往返吧
第一天:早上越早越好,成都新南门出发,直达峨眉山脚的游客中心,也就是常说的报国寺景区。然后游览报国寺、伏虎寺,从伏虎寺旁边山门进山,沿途雷音寺、纯阳殿、圣水阁、中峰寺,左手上坡走广福寺、清音阁,左手走一线天、猴区,然后到洪椿坪,住宿休息,庙子里住宿不贵的。如果不想吃素,就退回50米坡下一个晓雨食店吃饭吧,店主老刘头夫妇待人很厚道的。
第二天:早餐后出发,经过99道拐,到仙峰寺,然后是遇仙寺、九岭岗,左手走洗象池方向,然后是罗汉坡到雷洞坪。这一天景点不算多,但是爬坡厉害。就在雷洞坪休息吧,农家客栈很多,只要不是暑假和大假,都不算贵的。至少比金顶的住宿便宜几倍!
第三天:早点起来,这个季节想看日出至少要5点钟起床,半小时赶到接引殿缆车站,缆车上金顶看日出。如果不想乘坐缆车,那就要在提前一个小时起床,徒步大约2-2.5小时到金顶。
看了日出,游览舍身崖、金殿银殿、十方普贤、华藏寺,然后徒步下山回到雷洞坪、重回洗象池、九岭岗。这次走左手下山,沿途华严顶、初殿、细心所、万年寺。就住在万年寺吧,够累的了。
第四天:早饭后从万年寺回到清音阁,从五显岗出山,坐上景区的观光车,回到报国寺游客中心。如果想腐败一下,可以去灵秀温泉或者天颐温泉泡一泡。然后在游客中心乘坐班车直接回到成都新南门。
到峨眉山脚下,先在报国寺玩玩,风景不错,晚上住天下名山的天颐温泉,不贵,室内带温泉,个人泡过比较舒服的,第二天早上上金顶,耍一天,住一晚上寺庙感觉不错,第三天早上看日出,看完日出下山到万年寺,万年寺吃午饭,耍耍,下山到清音阁,清音阁风景不错,住一晚上,大概50一个人包吃住,第四天下山到峨眉城里面去吃吃土特产,什么曹鸭子、钵钵鸡、叶儿粑、豆腐脑、黄焖鸡、什么的。吃住的话就金顶贵点,那也是没办法的,其他都还好。不过先提醒,下山比上山痛,你也可以把我说的行程颠倒哈,看你们打算了。

posted @ 2019-09-24 11:20 狼爱上狸| 编辑 收藏

EOS现史诗级漏洞:半个月前就已发现,已有黑客盯上

https://baike.baidu.com/tashuo/browse/content?id=d44f4524beff55abe2205ce7&lemmaId=20441174&fromLemmaModule=pcBottom

posted @ 2019-09-17 08:40 狼爱上狸 阅读(15) | 评论 (0)编辑 收藏

2016:母亲河缘 —— 不老人生骑行黄河长江纪实(中国骑行黄河长江第一人)

http://bbs.biketo.com/thread-1799822-1-1.html

posted @ 2019-09-06 08:26 狼爱上狸 阅读(16) | 评论 (0)编辑 收藏

十年十万里之二:我绕长城转了一大圈

https://bbs.biketo.com/thread-1853758-1-1.html

posted @ 2019-09-06 08:04 狼爱上狸 阅读(18) | 评论 (0)编辑 收藏

不老人生骑行天下的故事

http://bbs.biketo.com/thread-856822-1-1.html

posted @ 2019-09-04 16:38 狼爱上狸 阅读(18) | 评论 (0)编辑 收藏

单人单车重走长征路骑行日记(49天6025公里跨10省)

http://bbs.8264.com/thread-2050898-1-1.html

posted @ 2019-09-04 09:11 狼爱上狸 阅读(15) | 评论 (0)编辑 收藏

赣州沿赣江骑行到南昌

https://www.meipian.cn/8k4hf0x

posted @ 2019-09-03 11:22 狼爱上狸 阅读(13) | 评论 (0)编辑 收藏

环鄱阳湖骑行

http://bbs.8264.com/thread-5512187-1-1.html

posted @ 2019-09-03 11:21 狼爱上狸 阅读(16) | 评论 (0)编辑 收藏

solc编译问题

1.安装solc
npm install -g solc
用IDEA编译sol时出现错误
solcjs.cmd --abi --bin CloudNoteService.sol -o C:\Users\Administrator\IdeaProjects\test
CloudNoteService.sol:1:1: ParserError: Source file requires different compiler version (current compiler is 0.5.10+commit.5a6ea5b1.Emscripten.clang - note that nightly builds are considered to be strictly less than the released version
pragma solidity ^0.4.22;
2.solcjs.cmd  --version//查看solc版本
0.5.10+commit.5a6ea5b1.Emscripten.clang
3.npm uninstall solc//卸载
4.npm install -g solc@0.4.24//安装solc0.4.24版本
5.C:\nodejs\node_modules\npm>solcjs.cmd --version//查看solc版本
0.4.24+commit.e67f0147.Emscripten.clang
6.solc跟web3一样,有版本的区别。

posted @ 2019-07-08 16:11 狼爱上狸 阅读(23) | 评论 (0)编辑 收藏

solidity官方开发文档

https://solidity-cn.readthedocs.io/zh/develop/

posted @ 2019-07-08 15:18 狼爱上狸 阅读(17) | 评论 (0)编辑 收藏

以太坊智能合约 —— 最佳安全开发指南

https://www.cnblogs.com/wanghui-garcia/p/9580573.html

posted @ 2019-07-07 15:57 狼爱上狸 阅读(18) | 评论 (0)编辑 收藏

IPFS + Ethereum(下篇):IPFS + Ethereum存储和获取图片

1. 项目描述

这篇文章通过truffle unbox react创建项目,安装ipfs-api,将图片存储到ipfs,将图片hash存储到Ethereum区块链,取数据时先从区块链读取图片hash,再通过hashipfs读取数据,解决了区块链大数据存储成本高昂的问题。

2. 效果图

3. 阅读本文需要掌握的知识

阅读本文需要将先学习上面的系列文章,由于本文前端使用了大量的React语法,所以建议学习一些React语法,还需要学习truffle framework

4. 源码

其实这篇文章的内容就是上面几篇文章的综合结合体,所以在这里我将不再对代码做过多的概述。

import React, {Component} from 'react' import SimpleStorageContract from '../build/contracts/SimpleStorage.json' import getWeb3 from './utils/getWeb3'  import './css/oswald.css' import './css/open-sans.css' import './css/pure-min.css' import './App.css'  const ipfsAPI = require('ipfs-api'); const ipfs = ipfsAPI({host: 'localhost', port: '5001', protocol: 'http'});  const contract = require('truffle-contract') const simpleStorage = contract(SimpleStorageContract) let account;  // Declaring this for later so we can chain functions on SimpleStorage. let contractInstance;  let saveImageOnIpfs = (reader) => {   return new Promise(function(resolve, reject) {     const buffer = Buffer.from(reader.result);     ipfs.add(buffer).then((response) => {       console.log(response)       resolve(response[0].hash);     }).catch((err) => {       console.error(err)       reject(err);     })   }) }  class App extends Component {   constructor(props) {     super(props)      this.state = {       blockChainHash: null,       web3: null,       address: null,       imgHash: null,       isWriteSuccess: false     }   }    componentWillMount() {      ipfs.swarm.peers(function(err, res) {       if (err) {         console.error(err);       } else {         // var numPeers = res.Peers === null ? 0 : res.Peers.length;         // console.log("IPFS - connected to " + numPeers + " peers");         console.log(res);       }     });      getWeb3.then(results => {       this.setState({web3: results.web3})        // Instantiate contract once web3 provided.       this.instantiateContract()     }).catch(() => {       console.log('Error finding web3.')     })   }    instantiateContract = () => {      simpleStorage.setProvider(this.state.web3.currentProvider);     this.state.web3.eth.getAccounts((error, accounts) => {       account = accounts[0];       simpleStorage.at('0x345ca3e014aaf5dca488057592ee47305d9b3e10').then((contract) => {         console.log(contract.address);         contractInstance = contract;         this.setState({address: contractInstance.address});         return;       });     })    }   render() {     return (<div className="App">       {         this.state.address           ? <h1>合约地址:{this.state.address}</h1>           : <div/>       }       <h2>上传图片到IPFS:</h2>       <div>         <label id="file">Choose file to upload</label>         <input type="file" ref="file" id="file" name="file" multiple="multiple"/>       </div>       <div>         <button onClick={() => {             var file = this.refs.file.files[0];             var reader = new FileReader();             // reader.readAsDataURL(file);             reader.readAsArrayBuffer(file)             reader.onloadend = function(e) {               console.log(reader);               saveImageOnIpfs(reader).then((hash) => {                 console.log(hash);                 this.setState({imgHash: hash})               });              }.bind(this);            }}>将图片上传到IPFS并返回图片HASH</button>       </div>       {         this.state.imgHash           ? <div>               <h2>imgHash:{this.state.imgHash}</h2>               <button onClick={() => {                   contractInstance.set(this.state.imgHash, {from: account}).then(() => {                     console.log('图片的hash已经写入到区块链!');                     this.setState({isWriteSuccess: true});                   })                 }}>将图片hash写到区块链:contractInstance.set(imgHash)</button>             </div>           : <div/>       }       {         this.state.isWriteSuccess           ? <div>               <h1>图片的hash已经写入到区块链!</h1>               <button onClick={() => {                   contractInstance.get({from: account}).then((data) => {                     console.log(data);                     this.setState({blockChainHash: data});                   })                 }}>从区块链读取图片hash:contractInstance.get()</button>             </div>           : <div/>       }       {         this.state.blockChainHash           ? <div>               <h3>从区块链读取到的hash值:{this.state.blockChainHash}</h3>             </div>           : <div/>       }       {         this.state.blockChainHash           ? <div>               <h2>浏览器访问:{"http://localhost:8080/ipfs/" + this.state.imgHash}</h2>               <img alt="" style={{                   width: 1600                 }} src={"http://localhost:8080/ipfs/" + this.state.imgHash}/>             </div>           : <img alt=""/>       }     </div>);   } }  export default App 

5. 源码修改

可以自己建立项目,也可以直接下载原博主的源码并进行修改。这里直接下载原博主的代码进行修改。

5.1 下载源码,安装依赖

$ git clone https://github.com/liyuechun/IPFS-Ethereum-Image.git $ cd IPFS-Ethereum-Image $ npm install 

5.2 查看源码端口

/Users/yuyang/IPFS-Ethereum-Image/src/utils/getWeb3.js

var provider = new Web3.providers.HttpProvider('http://127.0.0.1:9545') 

使用的端口是9545truffle develop 默认使用的端口就是9545,所以我们使用truffle develop作为测试私链。

5.3 启动私链

yuyangdeMacBook-Pro:IPFS-Ethereum-Image yuyang$ truffle develop Truffle Develop started at http://127.0.0.1:9545/  Accounts: (0) 0x627306090abab3a6e1400e9345bc60c78a8bef57 (1) 0xf17f52151ebef6c7334fad080c5704d77216b732 (2) 0xc5fdf4076b8f3a5357c5e395ab970b5b54098fef (3) 0x821aea9a577a9b44299b9c15c88cf3087f3b5544 (4) 0x0d1d4e623d10f9fba5db95830f7d3839406c6af2 (5) 0x2932b7a2355d6fecc4b5c0b6bd44cc31df247a2e (6) 0x2191ef87e392377ec08e7c08eb105ef5448eced5 (7) 0x0f4f2ac550a1b4e2280d04c21cea7ebd822934b5 (8) 0x6330a553fc93768f612722bb8c2ec78ac90b3bbc (9) 0x5aeda56215b167893e80b4fe645ba6d5bab767de  Private Keys: (0) c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3 (1) ae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f (2) 0dbbe8e4ae425a6d2687f1a7e3ba17bc98c673636790f1b8ad91193c05875ef1 (3) c88b703fb08cbea894b6aeff5a544fb92e78a18e19814cd85da83b71f772aa6c (4) 388c684f0ba1ef5017716adb5d21a053ea8e90277d0868337519f97bede61418 (5) 659cbb0e2411a44db63778987b1e22153c086a95eb6b18bdf89de078917abc63 (6) 82d052c865f5763aad42add438569276c00d3d88a2d062d36b2bae914d58b8c8 (7) aa3680d5d48a8283413f7a108367c7299ca73f553735860a87b08f39395618b7 (8) 0f62d96d6675f32685bbdb8ac13cda7c23436f63efbb9d07700d8669ff12b7c4 (9) 8d5366123cb560bb606379f90a0bfd4769eecc0557f1b362dcae9012b548b1e5  Mnemonic: candy maple cake sugar pudding cream honey rich smooth crumble sweet treat  ⚠️  Important ⚠️  : This mnemonic was created for you by Truffle. It is not secure. Ensure you do not use it on production blockchains, or else you risk losing funds. 

5.4 编译和部署合约

truffle(develop)> compile truffle(develop)> migrate 

5.5 获取合约地址

Using network 'develop'.  Running migration: 1_initial_migration.js   Deploying Migrations...   ... 0x130a37fb2d60e34cc04fccbfc51c10b988d61378090b89eb4546cce2a6ef3490   Migrations: 0x8cdaf0cd259887258bc13a92c0a6da92698644c0 Saving successful migration to network...   ... 0xd7bc86d31bee32fa3988f1c1eabce403a1b5d570340a3a9cdba53a472ee8c956 Saving artifacts... Running migration: 2_deploy_contracts.js   Deploying SimpleStorage...   ... 0x8c51da613e7c0517e726926c18d535aed0d21c8f4c82668212a6cdfd193d21d8   SimpleStorage: 0x345ca3e014aaf5dca488057592ee47305d9b3e10 Saving successful migration to network...   ... 0xf36163615f41ef7ed8f4a8f192149a0bf633fe1a2398ce001bf44c43dc7bdda0 Saving artifacts... 

SimpleStorage合约地址为0x345ca3e014aaf5dca488057592ee47305d9b3e10。也可以从/Users/yuyang/IPFS-Ethereum-Image/build/contracts/SimpleStorage.json看到

"networks": {     "4447": {       "events": {},       "links": {},       "address": "0x345ca3e014aaf5dca488057592ee47305d9b3e10",       "transactionHash": "0x8c51da613e7c0517e726926c18d535aed0d21c8f4c82668212a6cdfd193d21d8"     }   }, 

5.6 修改App.js文件

/Users/yuyang/IPFS-Ethereum-Image/src/App.js

instantiateContract = () => {      simpleStorage.setProvider(this.state.web3.currentProvider);     this.state.web3.eth.getAccounts((error, accounts) => {       account = accounts[0];       simpleStorage.at('0x345ca3e014aaf5dca488057592ee47305d9b3e10').then((contract) => {         console.log(contract.address);         contractInstance = contract;         this.setState({address: contractInstance.address});         return;       });     })   } 

将其中的0x345ca3e014aaf5dca488057592ee47305d9b3e10合约地址替换为你的合约地址。

6. 启动程序

新开命令行启动IPFS节点

yuyangdeMacBook-Pro:~ yuyang$ ipfs daemon 

新开命令行启动程序

yuyangdeMacBook-Pro:~ yuyang$ npm start 

7. 配置MetaMask插件和准备以太坊账号

程序启动后,会自动打开浏览器。注意,因为MetaMask插件只支持Chrome浏览器和FireFox浏览器,所以你需要运行保持页面运行在这两种浏览器上。关于MetaMask插件这部分内容,请查看这篇文章

因为我们的私链是部署在http://127.0.0.1:9545上的,所以你需要让MetaMask插件的端口也指向http://127.0.0.1:9545。点击Custom RPC进行配置后,切换端口为http://127.0.0.1:9545

因为需要向区块写入数据,需要花费gas,如果你的当前Account中没有以太币,可以导入其他的Account。点击右上角头像图标。

点击Import Account

需要输入私钥。在我们输入truffle develop启动私链的时候,已经分配给了我们十个Account地址和对应的私钥,任一账号都有100以太币,随便选择一个私钥填入。

Accounts: (0) 0x627306090abab3a6e1400e9345bc60c78a8bef57 (1) 0xf17f52151ebef6c7334fad080c5704d77216b732 (2) 0xc5fdf4076b8f3a5357c5e395ab970b5b54098fef (3) 0x821aea9a577a9b44299b9c15c88cf3087f3b5544 (4) 0x0d1d4e623d10f9fba5db95830f7d3839406c6af2 (5) 0x2932b7a2355d6fecc4b5c0b6bd44cc31df247a2e (6) 0x2191ef87e392377ec08e7c08eb105ef5448eced5 (7) 0x0f4f2ac550a1b4e2280d04c21cea7ebd822934b5 (8) 0x6330a553fc93768f612722bb8c2ec78ac90b3bbc (9) 0x5aeda56215b167893e80b4fe645ba6d5bab767de  Private Keys: (0) c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3 (1) ae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f (2) 0dbbe8e4ae425a6d2687f1a7e3ba17bc98c673636790f1b8ad91193c05875ef1 (3) c88b703fb08cbea894b6aeff5a544fb92e78a18e19814cd85da83b71f772aa6c (4) 388c684f0ba1ef5017716adb5d21a053ea8e90277d0868337519f97bede61418 (5) 659cbb0e2411a44db63778987b1e22153c086a95eb6b18bdf89de078917abc63 (6) 82d052c865f5763aad42add438569276c00d3d88a2d062d36b2bae914d58b8c8 (7) aa3680d5d48a8283413f7a108367c7299ca73f553735860a87b08f39395618b7 (8) 0f62d96d6675f32685bbdb8ac13cda7c23436f63efbb9d07700d8669ff12b7c4 (9) 8d5366123cb560bb606379f90a0bfd4769eecc0557f1b362dcae9012b548b1e5 

8. 运行程序

  1. 页面会显示当前合约的地址0x345ca3e014aaf5dca488057592ee47305d9b3e10

  2. 选择一张图片

  3. 点击上传到IPFS,并获取到图片hashQmSLnchQXh9gJrDKvQ5UFLZAj5f7icb2yWsWmcUKUYY3gj

  4. 点击将图片hash值保存到区块链,弹出MetaMask插件进行写入合约的确认

  5. 从区块链获取图片hashQmSLnchQXh9gJrDKvQ5UFLZAj5f7icb2yWsWmcUKUYY3gj

  6. 根据图片hash值,从IPFS进行访问

参考:【IPFS + 区块链 系列】 入门篇 - IPFS + Ethereum (下篇)-ipfs + Ethereum 大图片存储
作者:黎跃春



作者:yuyangray
链接:https://www.jianshu.com/p/3cb9520a23c0
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

posted @ 2019-07-07 15:04 狼爱上狸| 编辑 收藏

IPFS + Ethereum(上篇):JS+IPFS-API存储和获取数据

1. 内容简介

这篇文章将为大家讲解js-ipfs-api的简单使用,如何将数据上传到IPFS,以及如何从IPFS通过HASH读取数据。

2. IPFS-HTTP效果图

3. 实现步骤

3.1 安装create-react-app

参考文档:https://reactjs.org/tutorial/tutorial.html

yuyangdeMacBook-Pro:~ yuyang$ npm install -g create-react-app /Users/yuyang/.nvm/versions/node/v8.9.4/bin/create-react-app -> /Users/yuyang/.nvm/versions/node/v8.9.4/lib/node_modules/create-react-app/index.js + create-react-app@1.5.2 added 67 packages in 14.512s 

3.2 React项目创建

yuyangdeMacBook-Pro:~ yuyang$ create-react-app ipfs-http-demo  Creating a new React app in /Users/yuyang/ipfs-http-demo.  Installing packages. This might take a couple of minutes. Installing react, react-dom, and react-scripts...  ... ...   Success! Created ipfs-http-demo at /Users/yuyang/ipfs-http-demo Inside that directory, you can run several commands:    yarn start     Starts the development server.    yarn build     Bundles the app into static files for production.    yarn test     Starts the test runner.    yarn eject     Removes this tool and copies build dependencies, configuration files     and scripts into the app directory. If you do this, you can’t go back!  We suggest that you begin by typing:    cd ipfs-http-demo   yarn start  Happy hacking! 

3.3 运行React项目

yuyangdeMacBook-Pro:ipfs-http-demo yuyang$ npm start 
Compiled successfully!  You can now view ipfs-http-demo in the browser.    Local:            http://localhost:3000/   On Your Network:  http://192.168.0.4:3000/  Note that the development build is not optimized. To create a production build, use yarn build. 

3.4 浏览项目

浏览器会自动打开:http://localhost:3000/

效果如下:

3.5 安装ipfs-api

https://www.npmjs.com/package/ipfs-api

项目结构

安装ipfs-api

切换到项目根目录,安装ipfs-api

yuyangdeMacBook-Pro:ipfs-http-demo yuyang$ npm install --save ipfs-api  

ipfs-api安装完后,如上图所示,接下来刷新一下浏览器,看看项目是否有问题,正常来讲,一切会正常。

3.6 完成UI逻辑

拷贝下面的代码,将src/App.js里面的代码直接替换掉。

import React, { Component } from 'react'; import './App.css';  class App extends Component {         constructor(props) {           super(props);           this.state = {             strHash: null,             strContent: null           }       }      render() {       return (         <div className="App">           <input             ref="ipfsContent"            />           <button onClick={() => {             let ipfsContent = this.refs.ipfsContent.value;             console.log(ipfsContent);           }}>提交到IPFS</button>            <p>{this.state.strHash}</p>            <button onClick={() => {             console.log('从ipfs读取数据。')            }}>读取数据</button>            <h1>{this.state.strContent}</h1>         </div>       );     } }  export default App; 

上面的代码完成的工作是,当我们在输入框中输入一个字符串时,点击提交到IPFS按钮,将文本框中的内容取出来打印,后续我们需要将这个数据上传到IPFS。点击读取数据按钮,我们也只是随便打印了一个字符串,后面需要从IPFS读取数据,然后将读取的数据存储到状态机变量strContent中并且展示出来。

现在刷新网页,输入内容,点击提交到IPFS,Console打印出输入的内容。点击读取数据,Console打印出从ipfs读取数据。

3.7 导入IPFS

const ipfsAPI = require('ipfs-api'); const ipfs = ipfsAPI({host: 'localhost', port: '5001', protocol: 'http'}); 

3.8 编写上传大文本字符串到IPFS的Promise函数

saveTextBlobOnIpfs = (blob) => {     return new Promise(function(resolve, reject) {       const descBuffer = Buffer.from(blob, 'utf-8');       ipfs.add(descBuffer).then((response) => {         console.log(response)         resolve(response[0].hash);       }).catch((err) => {         console.error(err)         reject(err);       })     })   } 

response[0].hash返回的是数据上传到IPFS后返回的HASH字符串。

3.9 上传数据到IPFS

this.saveTextBlobOnIpfs(ipfsContent).then((hash) => {     console.log(hash);     this.setState({strHash: hash}); }); 

ipfsContent是从文本框中取到的数据,调用this.saveTextBlobOnIpfs方法将数据上传后,会返回字符串hash,并且将hash存储到状态机变量strHash中。

目前完整的代码:

import React, {Component} from 'react'; import './App.css';  const ipfsAPI = require('ipfs-api'); const ipfs = ipfsAPI({host: 'localhost', port: '5001', protocol: 'http'});  class App extends Component {    constructor(props) {     super(props);     this.state = {       strHash: null,       strContent: null     }   }    saveTextBlobOnIpfs = (blob) => {     return new Promise(function(resolve, reject) {       const descBuffer = Buffer.from(blob, 'utf-8');       ipfs.add(descBuffer).then((response) => {         console.log(response)         resolve(response[0].hash);       }).catch((err) => {         console.error(err)         reject(err);       })     })   }    render() {     return (<div className="App">       <input ref="ipfsContent" />       <button onClick={() => {           let ipfsContent = this.refs.ipfsContent.value;           console.log(ipfsContent);           this.saveTextBlobOnIpfs(ipfsContent).then((hash) => {             console.log(hash);             this.setState({strHash: hash});           });         }}>提交到IPFS</button>        <p>{this.state.strHash}</p>        <button onClick={() => {           console.log('从ipfs读取数据。')         }}>读取数据</button>       <h1>{this.state.strContent}</h1>     </div>);   } }  export default App; 

3.10 跨域资源共享CORS配置

跨域资源共享( CORS )配置,依次在终端执行下面的代码:

yuyangdeMacBook-Pro:ipfs-http-demo yuyang$ ipfs config --json API.HTTPHeaders.Access-Control-Allow-Methods '["PUT", "GET", "POST", "OPTIONS"]'  yuyangdeMacBook-Pro:ipfs-http-demo yuyang$ ipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin '["*"]'  yuyangdeMacBook-Pro:ipfs-http-demo yuyang$ ipfs config --json API.HTTPHeaders.Access-Control-Allow-Credentials '["true"]'  yuyangdeMacBook-Pro:ipfs-http-demo yuyang$ ipfs config --json API.HTTPHeaders.Access-Control-Allow-Headers '["Authorization"]'  yuyangdeMacBook-Pro:ipfs-http-demo yuyang$ ipfs config --json API.HTTPHeaders.Access-Control-Expose-Headers '["Location"]' 

用正确的端口运行daemon:

yuyangdeMacBook-Pro:ipfs-http-demo yuyang$ ipfs config Addresses.API /ip4/127.0.0.1/tcp/5001 yuyangdeMacBook-Pro:ipfs-http-demo yuyang$ ipfs config Addresses.API /ip4/127.0.0.1/tcp/5001 yuyangdeMacBook-Pro:ipfs-http-demo yuyang$ ipfs daemon 

3.11 刷新网页提交数据并在线查看数据

上传数据,并且查看返回hash值

在线查看上传到IPFS的数据

http://ipfs.io/ipfs/QmejvEPop4D7YUadeGqYWmZxHhLc4JBUCzJJHWMzdcMe2y

3.12 从IPFS读取数据

ipfs.cat(this.state.strHash).then((stream) => {     console.log(stream);     let strContent = Utf8ArrayToStr(stream);     console.log(strContent);     this.setState({strContent: strContent}); }); 

streamUint8Array类型的数据,下面的方法是将Uint8Array转换为string字符串。

Utf8ArrayToStr

function Utf8ArrayToStr(array) {     var out, i, len, c;     var char2, char3;      out = "";     len = array.length;     i = 0;     while(i < len) {     c = array[i++];     switch(c >> 4)       {         case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:           // 0xxxxxxx           out += String.fromCharCode(c);           break;         case 12: case 13:           // 110x xxxx   10xx xxxx           char2 = array[i++];           out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));           break;         case 14:           // 1110 xxxx  10xx xxxx  10xx xxxx           char2 = array[i++];           char3 = array[i++];           out += String.fromCharCode(((c & 0x0F) << 12) |                          ((char2 & 0x3F) << 6) |                          ((char3 & 0x3F) << 0));           break;         default:           break;       }     }      return out; } 

完整源码

import React, {Component} from 'react'; import './App.css';  const ipfsAPI = require('ipfs-api'); const ipfs = ipfsAPI({host: 'localhost', port: '5001', protocol: 'http'});  function Utf8ArrayToStr(array) {   var out,     I,     len,     c;   var char2,     char3;    out = "";   len = array.length;   i = 0;   while (i < len) {     c = array[i++];     switch (c >> 4) {       case 0:       case 1:       case 2:       case 3:       case 4:       case 5:       case 6:       case 7:         // 0xxxxxxx         out += String.fromCharCode(c);         break;       case 12:       case 13:         // 110x xxxx   10xx xxxx         char2 = array[i++];         out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));         break;       case 14:         // 1110 xxxx  10xx xxxx  10xx xxxx         char2 = array[i++];         char3 = array[i++];         out += String.fromCharCode(((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0));         break;       default:         break;     }   }    return out; }  class App extends Component {    constructor(props) {     super(props);     this.state = {       strHash: null,       strContent: null     }   }    saveTextBlobOnIpfs = (blob) => {     return new Promise(function(resolve, reject) {       const descBuffer = Buffer.from(blob, 'utf-8');       ipfs.add(descBuffer).then((response) => {         console.log(response)         resolve(response[0].hash);       }).catch((err) => {         console.error(err)         reject(err);       })     })   }    render() {     return (<div className="App">       <input ref="ipfsContent" />       <button onClick={() => {           let ipfsContent = this.refs.ipfsContent.value;           console.log(ipfsContent);           this.saveTextBlobOnIpfs(ipfsContent).then((hash) => {             console.log(hash);             this.setState({strHash: hash});           });         }}>提交到IPFS</button>        <p>{this.state.strHash}</p>        <button onClick={() => {           console.log('从ipfs读取数据。')           ipfs.cat(this.state.strHash).then((stream) => {             console.log(stream);             let strContent = Utf8ArrayToStr(stream);             console.log(strContent);             this.setState({strContent: strContent});           });         }}>读取数据</button>       <h1>{this.state.strContent}</h1>     </div>);   } }  export default App; 

4. 总结

这篇文章主要讲解如何配置React环境,如何创建React项目,如何安装js-ipfs-api,如何上传数据,如何设置开发环境,如何下载数据等等内容。通过这篇文章的系统学习,你会掌握js-ipfs-api在项目中的使用流程。



作者:yuyangray
链接:https://www.jianshu.com/p/48218aa9d724
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

posted @ 2019-07-07 15:03 狼爱上狸| 编辑 收藏

IPFS + Ethereum(中篇):图片存储到IPFS以及获取

1. 项目效果图

2. 创建React项目

yuyangdeMacBook-Pro:~ yuyang$ create-react-app ipfs_img 

3. 完成UI逻辑

将下面的代码拷贝替换掉App.js里面的代码。

import React, {Component} from 'react'  class App extends Component {   constructor(props) {     super(props)      this.state = {       imgSrc: null     }   }     render() {     return (<div className="App">        <h2>上传图片到IPFS:</h2>       <div>         <label id="file">Choose file to upload</label>         <input type="file" ref="file" id="file" name="file" multiple="multiple"/>       </div>       <div>         <button onClick={() => {             var file = this.refs.file.files[0];             var reader = new FileReader();             // reader.readAsDataURL(file);             reader.readAsArrayBuffer(file)             reader.onloadend = (e) => {               console.log(reader);             }            }}>Submit</button>       </div>       {         this.state.imgSrc             <div>               <h2>{"http://localhost:8080/ipfs/" + this.state.imgSrc}</h2>               <img alt="区块链部落" style= src={"http://localhost:8080/ipfs/" + this.state.imgSrc}/>             </div>           : <img alt=""/>       }     </div>);   } }  export default App 

4. 安装ipfs-api

yuyangdeMacBook-Pro:ipfs_img yuyang$ npm install --save ipfs-api 

5. App.js导入IPFS

const ipfsAPI = require('ipfs-api'); const ipfs = ipfsAPI({host: 'localhost', port: '5001', protocol: 'http'}); 

6. 实现上传图片到IPFS的Promise函数

let saveImageOnIpfs = (reader) => {   return new Promise(function(resolve, reject) {     const buffer = Buffer.from(reader.result);     ipfs.add(buffer).then((response) => {       console.log(response)       resolve(response[0].hash);     }).catch((err) => {       console.error(err)       reject(err);     })   }) } 

7. 上传图片到IPFS

var file = this.refs.file.files[0]; var reader = new FileReader(); // reader.readAsDataURL(file); reader.readAsArrayBuffer(file) reader.onloadend = function(e) {   console.log(reader);   saveImageOnIpfs(reader).then((hash) => {     console.log(hash);     this.setState({imgSrc: hash})   }); 
  • reader.readAsDataURL(file);上传图片路径。

  • reader.readAsArrayBuffer(file);上传图片内容。

上传图片

saveImageOnIpfs(reader).then((hash) => {     console.log(hash);     this.setState({imgSrc: hash})   }); 

hash即是上传到IPFS的图片的HASH地址,this.setState({imgSrc: hash})hash保存到状态机变量imgSrc中。

8. 完整代码

import React, {Component} from 'react'  const ipfsAPI = require('ipfs-api'); const ipfs = ipfsAPI({host: 'localhost', port: '5001', protocol: 'http'});  let saveImageOnIpfs = (reader) => {   return new Promise(function(resolve, reject) {     const buffer = Buffer.from(reader.result);     ipfs.add(buffer).then((response) => {       console.log(response)       resolve(response[0].hash);     }).catch((err) => {       console.error(err)       reject(err);     })   }) }  class App extends Component {   constructor(props) {     super(props)      this.state = {       imgSrc: null     }   }    render() {     return (       <div className="App">        <h2>上传图片到IPFS:</h2>       <div>         <label id="file">Choose file to upload</label>         <input type="file" ref="file" id="file" name="file" multiple="multiple"/>       </div>       <div>         <button onClick={() => {             var file = this.refs.file.files[0];             var reader = new FileReader();             // reader.readAsDataURL(file);             reader.readAsArrayBuffer(file)             reader.onloadend = (e) => {               console.log(reader);               saveImageOnIpfs(reader).then((hash) => {                 console.log(hash);                 this.setState({imgSrc: hash})               });             }            }}>Submit</button>       </div>       {         this.state.imgSrc             ?<div>               <h2>{"http://localhost:8080/ipfs/" + this.state.imgSrc}</h2>               <img alt="区块链部落" src={"http://localhost:8080/ipfs/" + this.state.imgSrc} />             </div>             :<img alt=""/>       }     </div>);   } }  export default App 

参考:【IPFS + 区块链 系列】 入门篇 - IPFS + Ethereum (中篇)-js-ipfs-api - 图片上传到IPFS以及下载

作者:黎跃春



作者:yuyangray
链接:https://www.jianshu.com/p/db2676952c48
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

posted @ 2019-07-07 15:01 狼爱上狸| 编辑 收藏

Ropsten申请测试币

http://faucet.ropsten.be:3001/上申请,只需要输入你在Ropsten网络上的账户地址就行,转币操作非常迅速,目前一次可申请1ETH,24小时后可再次申请;

posted @ 2019-07-05 21:59 狼爱上狸 阅读(19) | 评论 (0)编辑 收藏

校外访问

     摘要: 数字资源校外访问锦囊,拿走不谢! ...  阅读全文

posted @ 2019-07-05 11:17 狼爱上狸| 编辑 收藏

web3.eth.abi

1.web3的1.0以下版本不支持web3.eth.abi
2.var ethabi = require('web3-eth-abi');这种引用也有问题。
3.升级web3到1.0以上版本后测试通过:
var Web3 = require('web3');
var web3 = new Web3();

console.log(web3.eth.abi.encodeFunctionSignature('myMethod(uint256,string)'))

posted @ 2019-06-29 19:07 狼爱上狸 阅读(11) | 评论 (0)编辑 收藏

删除无用的系统服务项

方法: 在注册表中删除

运行regedit, 找到
HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Services 中想要删除的服务。

 

重启电脑可以看到你所选定的服务项在服务列表中不存在了

posted @ 2019-06-29 11:41 狼爱上狸 阅读(17) | 评论 (0)编辑 收藏

infura的使用

https://chaindesk.cn/witbook/1/12

posted @ 2019-06-27 22:45 狼爱上狸 阅读(36) | 评论 (0)编辑 收藏

sol在线测试

https://ethereum.github.io/browser-solidity/

posted @ 2019-06-27 21:00 狼爱上狸 阅读(19) | 评论 (0)编辑 收藏

ipfs和eth结合的例子

https://github.com/tooploox/ipfs-eth-database

posted @ 2019-06-26 08:21 狼爱上狸 阅读(19) | 评论 (0)编辑 收藏

第十一课 从宠物商店案例看DAPP架构和WEB3.JS交互接口

https://www.jianshu.com/p/47174718960b

posted @ 2019-06-25 11:05 狼爱上狸 阅读(18) | 评论 (0)编辑 收藏

truffle里的solc版本与实际solc版本冲突的问题

1.因为solc@0.5.1出现调用简单运算合约出现返回0的问题,所以把solc降到了0.4.22。
2.安装truffle后,npm install -g truffle,版本有所不同:
PS C:\> truffle version
Truffle v5.0.24 (core: 5.0.24)
Solidity v0.5.0 (solc-js)
Node v10.16.0
Web3.js v1.0.0-beta.37
3.建立简单合约Greeter.sol后,利用truffle compile后,出现:
Error: CompileError: ParsedContract.sol:1:1: ParserError: Source file requires different compiler version (current compiler is 0.5.8+commit.23d335f2.Emscripten.clang - note that nightly builds are considered to be strictly less than the released version
pragma solidity ^0.4.24;
^----------------------^

Compilation failed. See above.
4.修改truffle-config.js文件:
module.exports = {
// Uncommenting the defaults below
// provides for an easier quick-start with Ganache.
// You can also follow this format for other networks;
// see <http://truffleframework.com/docs/advanced/configuration>
// for more details on how to specify configuration options!
/*
networks: {
development: {
host: "127.0.0.1",
port: 7545,
network_id: "*"
},
test: {
host: "127.0.0.1",
port: 7545,
network_id: "*"
}
}
*/
compilers: {
solc: {
version: "0.4.24"
}
}
};
5.再次编译,出现
/C/users/administrator/webstormprojects/testtruffle/contracts/Migrations.sol:1:1: SyntaxError: Source file requires different compiler version (current compiler is 0.4.24+commit.e67f0147.Emscripten.clang - note that nightly builds are considered to be strictly less than the released version
pragma solidity >=0.4.25 <0.6.0;
^------------------------------^
6.打开Migrations.sol文件,
把pragma solidity >=0.4.25 <0.6.0;
修改为:pragma solidity >=0.4.24 <0.6.0;
编译通过。

posted @ 2019-06-25 09:05 狼爱上狸 阅读(53) | 评论 (0)编辑 收藏

ipfs + 以太坊实例解析

本文章的项目基于春哥的博客教程
【IPFS + 区块链 系列】 入门篇 - IPFS + Ethereum (下篇)-ipfs + Ethereum 大图片存储

我个人只是作为记录学习心得所借鉴
项目流程

首先调用代码创建truffle项目

    truffle unbox react

其次,要引入ipfs的api,用作图片存储的相关功能,我们是将图片存储到ipfs当中,而将所获得图片的hash区块链之中,区块链大数据成本的问题

    npm install –save ipfs-api

安装完毕调用complie编译合约代码,,以便使用web3调用合约存储区块链

    compile

替换合约地址,这个需要将合约在以太坊部署并取得对应地址
然后运行ipfs节点

    ipfs daemon

启动项目

    npm start

就可以看到项目成功
代码解读分析

import React, {Component} from 'react'
import SimpleStorageContract from '../build/contracts/SimpleStorage.json'
import getWeb3 from './utils/getWeb3'

import './css/oswald.css'
import './css/open-sans.css'
import './css/pure-min.css'
import './App.css'

const ipfsAPI = require('ipfs-api');
const ipfs = ipfsAPI({host: 'localhost', port: '5001', protocol: 'http'});

const contract = require('truffle-contract')
const simpleStorage = contract(SimpleStorageContract)
let account;

/** Declaring this for later so we can chain functions on SimpleStorage.**/
let contractInstance;
//ipfs保存图片方法//
let saveImageOnIpfs = (reader) => {
  return new Promise(function(resolve, reject) {
    const buffer = Buffer.from(reader.result);
    ipfs.add(buffer).then((response) => {
      console.log(response)
      resolve(response[0].hash);
    }).catch((err) => {
      console.error(err)
      reject(err);
    })
  })
}

//创建构造函数,添加状态机变量//

class App extends Component {
  constructor(props) {
    super(props)

    this.state = {
      blockChainHash: null,
      web3: null,
      address: null,
      imgHash: null,
      isWriteSuccess: false
    }
  }
//程序启动默认调用方法//
  componentWillMount() {
    //打印项目中网络节点//
    ipfs.swarm.peers(function(err, res) {
      if (err) {
        console.error(err);
      } else {
        /** var numPeers = res.Peers === null ? 0 : res.Peers.length;**/
        /** console.log("IPFS - connected to " + numPeers + " peers");**/
        console.log(res);
      }
    });
    //web3设置,同时调用初始化方法//
    getWeb3.then(results => {
      this.setState({web3: results.web3})

      // Instantiate contract once web3 provided.
      this.instantiateContract()
    }).catch(() => {
      console.log('Error finding web3.')
    })
  }
    //初始化合约实例、web3获取合约账号以及合约实例//
  instantiateContract = () => {

    simpleStorage.setProvider(this.state.web3.currentProvider);
    this.state.web3.eth.getAccounts((error, accounts) => {
      account = accounts[0];
      simpleStorage.at('0xf6a7e96860f05f21ecb4eb588fe8a8a83981af03').then((contract) => {
        console.log(contract.address);
        contractInstance = contract;
        this.setState({address: contractInstance.address});
        return;
      });
    })

  }
  render() {
    return (<div className="App">
      {
        this.state.address
          ? <h1>合约地址:{this.state.address}</h1>
          : <div/>
      }
      <h2>上传图片到IPFS:</h2>
      /**这一部分用于上传文件到ipfs**/
      <div>
        <label id="file">Choose file to upload</label>
        <input type="file" ref="file" id="file" name="file" multiple="multiple"/>
      </div>
      <div>
        <button onClick={() => {
            var file = this.refs.file.files[0];
            var reader = new FileReader();
            // reader.readAsDataURL(file);
            reader.readAsArrayBuffer(file)
            reader.onloadend = function(e) {
              console.log(reader);
              saveImageOnIpfs(reader).then((hash) => {
                console.log(hash);
                this.setState({imgHash: hash})
              });

            }.bind(this);

          }}>将图片上传到IPFS并返回图片HASH</button>
      </div>
       /**这一部分用于上传hash到区块链**/
      {
        this.state.imgHash
          ? <div>
              <h2>imgHash:{this.state.imgHash}</h2>
              <button onClick={() => {
                  contractInstance.set(this.state.imgHash, {from: account}).then(() => {
                    console.log('图片的hash已经写入到区块链!');
                    this.setState({isWriteSuccess: true});
                  })
                }}>将图片hash写到区块链:contractInstance.set(imgHash)</button>
            </div>
          : <div/>
      }
      {
        this.state.isWriteSuccess
          ? <div>
              <h1>图片的hash已经写入到区块链!</h1>
              <button onClick={() => {
                  contractInstance.get({from: account}).then((data) => {
                    console.log(data);
                    this.setState({blockChainHash: data});
                  })
                }}>从区块链读取图片hash:contractInstance.get()</button>
            </div>
          : <div/>
      }
      {
        this.state.blockChainHash
          ? <div>
              <h3>从区块链读取到的hash值:{this.state.blockChainHash}</h3>
            </div>
          : <div/>
      }
      {
        this.state.blockChainHash
          ? <div>
              <h2>浏览器访问:{"http://localhost:8080/ipfs/" + this.state.imgHash}</h2>
              <img alt="" style={{width:200}} src={"http://localhost:8080/ipfs/" + this.state.imgHash}/>
            </div>
          : <img alt=""/>
      }
    </div>);
  }
}

export default App



该项目算是truffle和ipfs结合以太坊一起使用的综合案例,用与梳理知识点
---------------------
作者:czZ__czZ
来源:CSDN
原文:https://blog.csdn.net/czZ__czZ/article/details/79036567
版权声明:本文为博主原创文章,转载请附上博文链接!

posted @ 2019-06-25 08:21 狼爱上狸 阅读(18) | 评论 (0)编辑 收藏

nodejs-执行报错Error: Cannot find module 'express'

  1. C:\Users\0>node E:\项目\2018年\11月份\nodejs\express_demo.js
  2. module.js:471
  3. throw err;
  4. ^
  5. Error: Cannot find module 'express'
  6. at Function.Module._resolveFilename (module.js:469:15)
  7. at Function.Module._load (module.js:417:25)
  8. at Module.require (module.js:497:17)
  9. at require (internal/module.js:20:19)
  10. at Object.<anonymous> (E:\项目\2018年\11月份\nodejs\express_demo.js:1:77)
  11. at Module._compile (module.js:570:32)
  12. at Object.Module._extensions..js (module.js:579:10)
  13. at Module.load (module.js:487:32)
  14. at tryModuleLoad (module.js:446:12)
  15. at Function.Module._load (module.js:438:3)
  16. C:\Users\0>express --version
  17. 4.16.0

实际上我是有安装express模块的

奇了个怪了。

然后试过1种方法是进入项目目录再执行安装express模块,无效

最后,原来是node_modules没有配置环境变量

配置上吧:

1、控制面板\所有控制面板项\系统\高级系统设置\环境变量

新建设‘NODE_PATH’:C:\Users\0\AppData\Roaming\npm\node_modules

 编辑增加环境变量‘PATH’

完美~~


http://www.pianshen.com/article/837378161/


posted @ 2019-06-23 22:31 狼爱上狸 阅读(16) | 评论 (0)编辑 收藏

调用智能合约简单运算总返回0的问题

1.合约内容
pragma
solidity ^0.5.9;

contract hello {

function mutiply(uint a) public pure returns (uint result) {

return a*3;

}
}
2.部署合约:
var Web3 = require("web3");
var fs = require("fs");
var web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545'));
var code = '0x' + fs.readFileSync("2_sol_hello.bin").toString();
var abi = JSON.parse(fs.readFileSync("2_sol_hello.abi").toString());
var contract = web3.eth.contract(abi);
console.log(web3.eth.accounts);
console.log('account balance:' + web3.eth.getBalance(web3.eth.accounts[0]))

web3.personal.unlockAccount(web3.eth.accounts[0],"123")
var contract = contract.new({from: web3.eth.accounts[0], data: code, gas: 470000},
function(e, contract){

if(!contract.address) {
console.log("已经发起交易,交易地址:" + contract.transactionHash + "\n正在等待挖矿");
} else {
console.log("智能合约部署成功,地址:" + contract.address);

}

}
)
3.调用合约
var Web3 = require("web3");
var fs = require("fs");
var web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545'));
var abi = JSON.parse(fs.readFileSync("2_sol_hello.abi").toString());
var contract = web3.eth.contract(abi);
var instance = contract.at('0xb06846c54c6ae67102ed67ce57a357a643d1f1b8')
web3.personal.unlockAccount(web3.eth.accounts[0],"123")
console.log(instance.mutiply(12).toString())
4.显示结果为:
0
原因:solc版本0.5.9太高,可能调用的方法不对。
解决方法:npm install -g solc@0.4.22
降低版本,然后把合约第一行改为:
pragma solidity ^0.4.22;
问题解决。

posted @ 2019-06-23 18:12 狼爱上狸 阅读(33) | 评论 (0)编辑 收藏

以太坊(二)MAC搭建以太坊私有链多节点集群(同一台电脑)

https://www.jianshu.com/p/52e9588116ad

posted @ 2019-06-20 14:47 狼爱上狸 阅读(15) | 评论 (0)编辑 收藏

web3.php Error: The method personal_newAccount does not exist/is not available

很多人遇到这个问题:

web3.php Error: The method personal_newAccount does not exist/is not available。

其实很简单,我们只需要在geth启动时的rpc参数中设置rpcapi时包括 "personal" 即可。

geth --rpc --rpcaddr 0.0.0.0 --rpcport 8545 --rpcapi eth,web3,admin,personal,net


来自:http://www.bcfans.com/toutiao/redian/101819.html


我的是:
geth --identity "Water" --rpc --rpcport "8080" --rpccorsdomain "*" --datadir gethdata --port "30303" --nodiscover --rpcapi "db,eth,net,personal,web3" --networkid 1999 init genesis.json

posted @ 2019-06-19 10:42 狼爱上狸 阅读(22) | 评论 (0)编辑 收藏

windows安装web3

1.安装web3要先安装node。
2.cmd->powershell
3.c:\>node
  >require('web3')
结果输出一些错误,表明还没安装web3。
4.c:\>npm install web3
5.安装后,再
 c:\>node
  >require('web3')
输出
[Function:Web3]
表明web3就安装好了。

posted @ 2019-06-17 14:26 狼爱上狸 阅读(37) | 评论 (1)编辑 收藏

本地自动化编译、部署和调用智能合约

https://blog.csdn.net/qiubingcsdn/article/details/89703128

posted @ 2019-06-15 23:05 狼爱上狸 阅读(31) | 评论 (0)编辑 收藏

本地搭建以太坊私有网络-基于Ganache和MetaMask

    背景介绍

本文主要介绍如何使用Ganache,在本地搭建以太坊私有网络,并进行简单的测试。

 

    所需软件

      Ganache

Ganache用于搭建私有网络。在开发和测试环境下,Ganache提供了非常简便的以太坊私有网络搭建方法,通过可视化界面可以直观地设置各种参数、浏览查看账户和交易等数据。

下载地址为:https://truffleframework.com/ganache/

        MetaMask

MetaMask用于测试私有网络。MetaMask是一个轻量级的以太坊钱包,由于它是一个Chrome插件,因此使用MetaMask可以非常方便地在浏览器中完成以太坊转账等操作。

下载地址为:https://www.metamask.io

 

    操作步骤

     安装、启动Ganache

1. 使用安装包安装即可。

2. 打开程序后,会显示以下界面,用户可以查看账户(默认创建10个账户)、区块、交易和日志。

 

3. 点击“设置”,如下图所示,用户还可以设置绑定的ip和端口(设置为8545即可,稍后MetaMask会用这个端口)、账户数量以及gas限制等,点击“restart”后设置生效。

 

此时,Ganache已经在本机运行了一个以太坊私有网络,并绑定了8545端口。

 

    安装、启动MetaMask

1. 把插件添加到chrome扩展程序即可

2. 点击Chrome中的MetaMask图标,按照每一步提示启动MetaMask

3. 如下图所示,设置MetaMask连接到本地的以太坊私有网络

    

此时,MetaMask就可以和本地的以太坊私有网络进行交互了。

 

    用MetaMask测试私有网络

1. 从Ganache创建的账户中选择一个导入到MetaMask中

    a. 在Ganache账户页面选定一个账户,点击最右边的小钥匙图标,复制其私钥(private key)

    b. 在MetaMask中点击头像,选择 “import account”,弹出对话框

    c.  把复制的账户私钥填入文本框中,并点击“import”

 

此时,MetaMask就可以操作这个新账户了。

 

2. 用新导入的账户进行转账

    a. 点击“send”按钮,弹出转账对话框

    b. 从Ganache账户页面中,再选定一个其他的账户,复制其地址

    c. 把复制的地址填入到 “to” 文本框中,并在“amount”文本框中填入一个数值,表示要转账的金额(如 “10”);其它文本框默认值即可

    d. 点击next,弹出转账确认框,点击“confirm”确认交易

    e. 提醒转账成功后,可以看到账户余额发生了变化,此时再转到Ganache账户页面,也可看到两个账户的余额也都发生了变化。

 

    注意

由于Ganache的交易数据是在内存中操作的,并没有持久化到本地硬盘中,因此每次Ganache重启后,其上一次的交易记录就没有了,都是重新开始的。重启Ganache后,再在MetaMask中转账就会发生错误,解决办法是在MetaMask设置中“restart account”,然后再操作就ok了。

如果想保留Ganache每一次运行时的交易数据,以便下一次继续使用,可以使用命令行的形式ganache-cli启动Ganache,并指定数据存储目录
---------------------
作者:BigCuttie
来源:CSDN
原文:https://blog.csdn.net/starleelzx/article/details/82943530
版权声明:本文为博主原创文章,转载请附上博文链接!

posted @ 2019-06-13 22:51 狼爱上狸 阅读(38) | 评论 (0)编辑 收藏

webstrom下载安装

1.https://www.jetbrains.com/webstorm/download/ 下载2019.1.3版

2.在网盘开发软件下载JetbrainsCrack3.4.jar、汉化包和激活码软件。
3.将解压的.jar 破解补丁放在你的安装idea下面的bin的目录下面。如C:\JetBrains\WebStorm\bin
4.在安装的idea下面的bin目录下面有2个文件 : 一个是webstorm.exe.vmoptions,还有一个是webstorm64.exe.vmoptions。用记事本打开 分别在最下面一行增加一行:
-javaagent:C:\JetBrains\WebStorm\bin\JetbrainsCrack3.4.jar
5.重启一下软件,在进入出现有active code选择界面的时候,打开激活码.txt文件,输入即可,能够进入应用界面则表示安装破解成功

posted @ 2019-06-11 10:04 狼爱上狸 阅读(17) | 评论 (0)编辑 收藏

安装intelliJ IDEA2018.3

1.https://www.jetbrains.com/idea/download/previous.html 下载2018.3.6版本;

2.在网盘开发软件下载JetbrainsCrack_jb51.rar软件,里面包含了JetbrainsCrack-4.2-release-enc.jar文件。
3.将解压的.jar 破解补丁放在你的安装idea下面的bin的目录下面。如C:\JetBrains\IntelliJ\bin
4.在安装的idea下面的bin目录下面有2个文件 : 一个是idea64.exe.vmoptions,还有一个是idea.exe.vmoptions。用记事本打开 分别在最下面一行增加一行:
-javaagent:C:\JetBrains\IntelliJ\bin\JetbrainsCrack-4.2-release-enc.jar
5.重启一下软件,在进入出现有active code选择界面的时候,随便输入几个字母即可,能够进入应用界面则表示安装破解成功。

posted @ 2019-06-11 09:33 狼爱上狸 阅读(40) | 评论 (3)编辑 收藏

Ubuntu16 升级nodejs版本

背景

Ubuntu16下,使用apt-get下载的nodejs最新版本为v4.2.6,而react-native需要v8.x及以上的版本
解决方法

在网上找到了这一篇博客Ubuntu安装最新版nodejs,用npm安装了Node工具包n,使用该工具包将nodejs安装到了目前的最新版本v10.6.0。在已经安装npm的基础上,具体操作如下:

sudo npm install n -g

sudo n stable

node -v

n是一个Node工具包,它提供了几个升级命令参数:

n 显示已安装的Node版本
n latest 安装最新版本Node
n stable 安装最新稳定版Node
n lts 安装最新长期维护版(lts)Node
n version 根据提供的版本号安装Node
---------------------
作者:LDY_T
来源:CSDN
原文:https://blog.csdn.net/u010277553/article/details/80938829
版权声明:本文为博主原创文章,转载请附上博文链接!

posted @ 2019-06-10 11:07 狼爱上狸 阅读(18) | 评论 (0)编辑 收藏

献给那些安装remix-ide一直不成功的windows用户

首先找到编译器git地址,https://github.com/ethereum/remix-ide

进来后有安装步骤

/home/water/下载/3486521-922a751008a61222.png
remix-ide.png

如果我们电脑上没有node.js先登录下面的网址安装
https://docs.npmjs.com/getting-started/installing-node
因为安装的过程中需要的权限功能比较多所以得用管理员执行powershell 不建议使用cmd操作
安装好之后查看自己的 输入命令npm -v ,查看npm版本号如果低于6.1.0。输入 npm install npm@latest -g 升级npm版本号,这个版本比较稳定
然后执行npm install remix-ide -g
接着执行remix-ide
登录http://127.0.0.1:8080
如果不成功 执行 npm install --global --production windows-build-tools
然后再执行上面的步骤八成就可以了,remix-ide需要的环境还挺多



作者:刘阿火
链接:https://www.jianshu.com/p/fb198cd619b9
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

posted @ 2019-06-10 09:47 狼爱上狸 阅读(29) | 评论 (0)编辑 收藏

windows之geth账户建立

建立新账号,最好用>personal.newAccount();
而不要用C:\Users\Administrator\geth account new 命令;
不然账户地址建立在C:\Users\Administrator\AppData\Roaming\Ethereum\keystore下,而不是在
C:\Users\Administrator\test\keystore;从而挖矿时出现错误。

posted @ 2019-06-08 19:18 狼爱上狸 阅读(18) | 评论 (0)编辑 收藏

IPFS(DRAFT 3) 中文版白皮书

https://blog.csdn.net/easylover/article/details/82733578

posted @ 2019-06-04 22:25 狼爱上狸 阅读(10) | 评论 (0)编辑 收藏

Akasha——基于以太坊和IPFS的社交网络

在Akasha项目组测试各种代币模型并追求最优解决方案之后。

Akasha项目同时使用了以太坊和IPFS技术,创建一个去中心化的社交网络。以太坊提供了身份系统、微支付等支持,IPFS提供了内容存储、分发等支持。最近Akasha发布了0.3.0测试版,爱折腾的用户可以在Akasha创建的以太坊私有测试网络上体验这个追逐理想的项目。

说再多的理论,不如动手尝试。现在使用Akasha比较容易,无论你使用Windows操作系统,还是Mac操作系统,还是Linux系统,都可以一键安装。下载地址:https://github.com/AkashaProject/Alpha/releases/tag/0.3.0

安装完成后,进入设置阶段。如果你以前安装过以太坊Go客户端或者IPFS客户端,选择“Advanced”,自定义配置。如果没有安装过,选择“Express setup”(快速安装)。

Akasha后台的以太坊Go客户端和IPFS客户端开始运行,等到以太坊客户端同步区块到最新就可以进入Akasha网络。


同步结束后,就可以进行注册。填写完注册信息后,点击Submit(提交)。提交这一操作会发送一笔交易,当这笔交易被矿工打包的区块中,注册就成功了。

Identity Registered ! 注册成功。开始畅游Akasha世界


进入你的个人主页。你可以关注某人(欢迎关ע@shaoping:)、某个主题。


当然你也可以发表状态。每个状态需要至少加一个标签(tag)才能发布,你可以添加已有的标签,例如ethfans。你也可以自己创建一个新标签,创建新标签也会通过发送交易实现的。


Akasha支持Whisper协议,可以在聊天室聊天。


Akasha官网:https://akasha.world/

来源:以太坊爱好者 http://ethfans.org/posts/Akasha-release-0-3-0

posted @ 2019-06-04 09:20 狼爱上狸 阅读(13) | 评论 (0)编辑 收藏

有趣的椭圆曲线加密

     摘要: 一、概述 椭圆曲线加密算法依赖于椭圆曲线理论,后者理论涵盖的知识比较深广,而且涉及数论中比较深奥的问题。经过数学家几百年的研究积累,已经有很多重要的成果,一些很棘手的数学难题依赖椭圆曲线理论得以解决(比如费马大定理)。 本文涉及的椭圆曲线知识只是抽取与密码学相关的很小的一个角落,涉及到很浅的理论的知识,同时也是一点比较肤浅的总结和认识,重点是利用椭圆曲线结合数学技巧阐述加密算法的过程和原理。 本文...  阅读全文

posted @ 2019-06-01 17:09 狼爱上狸 阅读(20) | 评论 (0)编辑 收藏

ipfs私有网络搭建

ipfs私有网络搭建准备工作:

1、至少准备2个ipfs的节点

2、创建一个共享秘钥

3、配置需要相互共享的节点。

一、准备IPFS节点。

1、准备两台linux节点,我测试的系统是Ubuntu 18.04 LTS(点击可以下载)。

2、安装ipfs命令:(如果已安装可以沪铝忽略)

        sudo snap install ipfs

3、安装go-lang环境,后面创建共享秘钥需要用到。(如果已安装请忽略)

        sudo apt-get install golang

4、安装git。(如果已经安装请忽略)

        sudo apt-get install git

两台linux服务器均完成ipfs安装之后第一步准备工作便已完成。

二、创建共享秘钥

1、到github上面下载秘钥生成工具go-ipfs-swarm-key-gen

        sudo git clone https://github.com/Kubuxu/go-ipfs-swarm-key-gen.git

2、编译go-ipfs-swarm-key-gen

        sudo go build -o ipfs-swarm-key-gen go-ipfs-swarm-key-gen/ipfs-swarm-key-gen/main.go

在当前目录会成一个ipfs-swarm-key-gen的可执行二进制文件。然后使用该文件生成一个swarm.key文件

        sudo ./ipfs-swarm-key-gen > swarm.key

拷贝swarm.key文件到.ipfs目录中。(注意使用snap安装ipfs那么.ipfs目录在~/snap/ipfs/目录下,例如我的是在~/snap/ipfs/589/下)。

三、配置相互共享的私有网络

1、分别初始化两个ipfs节点。

        ipfs init

2、删除ipfs默认的网关节点

        ipfs bootstrap rm all

3、添加其中一台节点的地址到另一台节点的bootstrap列表中。

    3.1执行ipfs id查看ipfs节点的ID值。

ipfs节点信息

    3.2添加节点地址到另一台节点的bootstrap列表中

ipfs bootstrap add /ip4/被添加节点的ip地址/tcp/4001/ipfs/被添加节点的ID值。

至此ipfs私有网络搭建完毕



作者:embedsky
链接:https://www.jianshu.com/p/cf70c5bc81ae
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

posted @ 2019-06-01 10:14 狼爱上狸 阅读(24) | 评论 (0)编辑 收藏

Ubuntu安装ipfs

sudo snap install ipfs

posted @ 2019-06-01 09:22 狼爱上狸 阅读(18) | 评论 (0)编辑 收藏

win10时间不同步怎么办

1.cmd
2.services.msc
3.Remote Procedure Call(RPC) Locator 自动启动
4.与Internet时间服务器同步 选择 time.windows.com

posted @ 2019-05-30 09:58 狼爱上狸 阅读(15) | 评论 (0)编辑 收藏

ubuntu 下查看caj文件

网的学位论文只有CAJ版,而我又偏偏使用Ubuntu,所以就有了这篇文章。

 

前端时间发现第一种方法在ubuntu 16 上不行, 请使用第二种方法。

 

第一种方法:

环境:Ubuntu 14.04 64bit

1.安装wine:

sudo apt-get install wine

2.下载caj6.0绿色版CAJViewer6.0_green.rar: http://pan.baidu.com/s/1mhwEvAK

3.解压到目录cajviewer6.0:

mkdir cajviewer6.0 unrar x CAJViewer6.0_green.rar cajviewer6.0

4.运行:

sudo chmod u+x CAJViewer.exe //修改权限 wine CAJViewer.exe 

结果如图:

 

PS: 由于我装的是英文版系统,所以有乱码,但将就着还可以看啦~

 

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

第二种方法:

前段时间发现用Ubuntu16.04上边的这种不行了,请使用下边的方法:

下载链接: http://pan.baidu.com/s/1jIqHxLs

      或 http://download.csdn.net/detail/arhaiyun/5457947

压缩包里边有安装说明,这里边是7.2 的cajviewer版本。亲测可用。


来自:https://www.cnblogs.com/asmer-stone/p/5197307.html

posted @ 2019-05-28 09:48 狼爱上狸 阅读(142) | 评论 (1)编辑 收藏

解决ubuntu-18-04使用root账户登录图形界面认证失败

https://morton.li/%E8%A7%A3%E5%86%B3ubuntu-18-04%E4%BD%BF%E7%94%A8root%E8%B4%A6%E6%88%B7%E7%99%BB%E5%BD%95%E5%9B%BE%E5%BD%A2%E7%95%8C%E9%9D%A2%E8%AE%A4%E8%AF%81%E5%A4%B1%E8%B4%A5/

posted @ 2019-05-27 09:07 狼爱上狸 阅读(21) | 评论 (0)编辑 收藏

搭建基于hyperledger fabric的联盟社区 --生成公私钥证书及配置文件

一.生成公私钥和证书

Fabric中有两种类型的公私钥和证书,一种是给节点之前通讯安全而准备的TLS证书,另一种是用户登录和权限控制的用户证书。这些证书本来应该是由CA来颁发,但是目前只有两个社区,所以目前暂时没有启用CA节点,但是Fabric帮我们提供了一个crytogen工具来生成证书。

 

1.1编译cryptogen

编译生成 cryptogen之前我们需要安装一个软件包,否则编译时会报错

sudo apt install libltdl3-dev

Fabric提供了专门编译cryptogen的入口,我们只需要运行以下命令即可:

cd ~/go/src/github.com/hyperledger/fabric make cryptogen

运行后系统返回如下结果即代表编译成功了

build/bin/cryptogen  CGO_CFLAGS=" " GOBIN=/home/studyzy/go/src/github.com/hyperledger/fabric/build/bin go install -tags "" -ldflags "-X github.com/hyperledger/fabric/common/tools/cryptogen/metadata.Version=1.0.0" github.com/hyperledger/fabric/common/tools/cryptogen  Binary available as build/bin/cryptogen

我们在build/bin文件夹下就可以看到编译出来的cryptogen程序。

 

1.2配置crypto-config.yaml

examples/e2e_cli/crypto-config.yaml已经提供了一个Orderer Org和两个Peer Org的配置,该模板中也对字段进行了注释。我们可以把配置修改一下:

OrdererOrgs:        - Name: Orderer     Domain: example.com               Specs:       - Hostname: orderer  PeerOrgs:      - Name: Org1     Domain: org1.example.com           Template:       Count: 1            Users:       Count: 1      - Name: Org2     Domain: org2.example.com     Template:       Count: 1     Users:       Count: 1

 

Name和Domain就是关于这个组织的名字和域名,这主要是用于生成证书的时候,证书内会包含该信息。而Template Count=1是说我们要生成1套公私钥和证书,因为我们一个组织只需要一个peer节点。最后Users. Count=1是说每个Template下面会有几个普通User(注意,Admin是Admin,不包含在这个计数中),这里配置了1,也就是说我们只需要一个普通用户User1@org2.example.com 我们可以根据实际需要调整这个配置文件,增删Org Users等。

 

1.3生成公司钥和证书

我们配置好crypto-config.yaml文件后,就可以用cryptogen去读取该文件,并生成对应的公私钥和证书了:

cd examples/e2e_cli/ ../../build/bin/cryptogen generate --config=./crypto-config.yaml

生成的文件都保存到crypto-config文件夹,我们可以进入该文件夹查看生成了哪些文件:

tree crypto-config

二.生成创世区块和Channel配置区块

2.1编译生成configtxgen

与前面1.1说到的类似,我们可以通过make命令生成configtxgen程序:

cd ~/go/src/github.com/hyperledger/fabric  make configtxgen

运行后的结果为:

build/bin/configtxgen  CGO_CFLAGS=" " GOBIN=/home/studyzy/go/src/github.com/hyperledger/fabric/build/bin go install -tags "nopkcs11" -ldflags "-X github.com/hyperledger/fabric/common/configtx/tool/configtxgen/metadata.Version=1.0.0" github.com/hyperledger/fabric/common/configtx/tool/configtxgen  Binary available as build/bin/configtxgen

2.2配置configtx.yaml

官方提供的examples/e2e_cli/configtx.yaml这个文件里面配置了由2个Org参与的Orderer共识配置TwoOrgsOrdererGenesis,以及由2个Org参与的Channel配置:TwoOrgsChannel。Orderer可以设置共识的算法是Solo还是Kafka,以及共识时区块大小,超时时间等,我们使用默认值即可,不用更改。而Peer节点的配置包含了MSP的配置,锚节点的配置。如果我们有更多的Org,或者有更多的Channel,那么就可以根据模板进行对应的修改。

2.3生成创世区块

配置修改好后,我们就用configtxgen 生成创世区块。并把这个区块保存到本地channel-artifacts文件夹中:

cd examples/e2e_cli/  ../../build/bin/configtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block

2.4生成Channel配置区块

../../build/bin/configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID mychannel

另外关于锚节点的更新,我们也需要使用这个程序来生成文件:

../../build/bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID mychannel -asOrg Org1MSP  ../../build/bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID mychannel -asOrg Org2MSP

最终,我们在channel-artifacts文件夹中,应该是能够看到4个文件。

channel-artifacts/ 
├── channel.tx 
├── genesis.block 
├── Org1MSPanchors.tx 
└── Org2MSPanchors.tx

posted @ 2019-05-20 14:59 狼爱上狸 阅读(43) | 评论 (0)编辑 收藏

Ubuntu下5大图像查看软件

1. Gwenview

是较好的一项应用,支持几乎所有图片格式,可进行基本的编辑、标签、缩略图、全屏、幻灯显示功能等等。

安装

sudo apt-get install gwenview


2. Eye of GNOME

是GNOME环境下较好的图片查看器,支持JPG, PNG, BMP, GIF, SVG, TGA, TIFF or XPM等图片格式,也可放大、幻灯显示图片、全屏、缩略图等功能。

安装

sudo apt-get install eog


3. gThumb

是另一GTK图片查看器,可导入Picasa或Flickr图片,也可导出到 Facebook, Flickr, Photobucker, Picasa 和本地文件夹。

安装

sudo apt-get install gthumb


4. Viewnior

是小型化的图片查看器,支持JPG和PNG格式。

安装

sudo apt-get install viewnior


5.gPicView

是LXDE下的默认图片查看器,操作按钮位于窗口底部。只需右击图片,实现所有相关功能。支持JPG, TIFF, BMP, PNG , ICO格式。

安装

sudo apt-get install gpicview

https://www.linuxidc.com/Linux/2011-03/33659.htm

posted @ 2019-05-20 14:57 狼爱上狸 阅读(25) | 评论 (0)编辑 收藏

以太坊多节点(两个节点)私链搭建

https://blog.csdn.net/apple9005/article/details/81282735

posted @ 2019-05-20 08:15 狼爱上狸 阅读(15) | 评论 (0)编辑 收藏

ubuntu apt-get 安装 golang 版本过低问题

apt-get install golang-go这样安装版本可能过低。
go version查看版本为 1.6.2
apt-get 卸载此版本重新安装

重新安装

    1. 去官网查看最新版链接 https://studygolang.com/dl
      比如我要下的是 https://studygolang.com/dl/golang/go1.11.linux-amd64.tar.gz
    1. 下载
      wget https://studygolang.com/dl/golang/go1.11.linux-amd64.tar.gz
         也可以到go语言中文网https://studygolang.com/dl下载最新版
    1. 解压缩
      tar -zxvf go1.11.linux-amd64.tar.gz -C /usr/lib
    将解压后的文件夹go移动到  /usr/local 

     输入命令: sudo mv go /usr/local

    1. 设置添加环境变量
      sudo gedit ~/.profile 在最后面添加如下配置
         export PATH=$PATH:/usr/local/go/bin   或者
export GOPATH=/opt/gopath export GOROOT=/usr/lib/go export GOARCH=386 export GOOS=linux export GOTOOLS=$GOROOT/pkg/tool export PATH=$PATH:$GOROOT/bin:$GOPATH/bin 

卸载老的go
sudo apt-get remove golang-go
    1. 安装新版本
      source ~/.profile
    1. 查看版本
      go version
      结果 go version go1.11 linux/amd64

参考:
https://blog.csdn.net/Booboochen/article/details/82463162
https://www.jianshu.com/p/85e98e9b003d

posted @ 2019-05-18 06:38 狼爱上狸 阅读(295) | 评论 (0)编辑 收藏

ubuntu18.04下最好用的音乐软件!没有之一

      自从2015年开始使用ubuntu之后,就开始了各种折腾。可惜的是,linux下,能用的音乐软件实在是少之又少!网易云音乐勉强可以,但是经常打不开。烦死。偶然发现这个软件:CoCoMusic,才惊觉是ubuntu 18.04.2下最好用的音乐软件!没有之一!      同时也适用于linux mint19.1。即点即开!堪称是,linux下的酷狗音乐!下载地址:https://github.com/xtuJSer/CoCoMusic/releases,直接下载:cocomusic_2.0.4_amd64.deb安装即可。

~$ cocomusic
即可启动

https://www.ubuntukylin.com/ukylin/forum.php?mod=viewthread&tid=188255

posted @ 2019-05-17 22:11 狼爱上狸 阅读(38) | 评论 (0)编辑 收藏

ubuntu18.04安装扫描仪

Linux下一般使用sane做为扫描仪后端,安装如下:
      sudo apt-get install sane sane-utils xsane

@node1:~$ sudo sane-find-scanner
  # sane-find-scanner will now attempt to detect your scanner. If the
  # result is different from what you expected, first make sure your
  # scanner is powered up and properly connected to your computer.

  # No SCSI scanners found. If you expected something different, make sure that
  # you have loaded a kernel SCSI driver for your SCSI adapter.

could not fetch string descriptor: Pipe error
could not fetch string descriptor: Pipe error
found USB scanner (vendor=0x04a9 [Canon], product=0x190d [CanoScan]) at libusb:003:006
  # Your USB scanner was (probably) detected. It may or may not be supported by
  # SANE. Try scanimage -L and read the backend's manpage.

$ scanimage -L
device `pixma:04A9190D' is a CANON Canoscan 9000F Mark II multi-function peripheral

期间也曾装过VueScan,可以识别扫描仪,但是要收费。
$ simple-scan
终于可以使用扫描仪了。

posted @ 2019-05-17 11:25 狼爱上狸 阅读(145) | 评论 (0)编辑 收藏