一.新的开始
大家好,我是小Co。和很多人一样,我也是最近才接触区块链,便立即决定投入区块链的研究当中,在币乎的某位大神的引导下,我来到了这个分享的世界。众所周知,区块链的起源,是由08年中本聪发布比特币白皮书为开端的,而区块链革命是他09年发布初代比特币源码才正式开始的。作为程序员,我深刻感受到了software redefine the world(软件重定义世界)带来的震撼,同时作为一名区块链小白,也迫不及待的想加入到这场金融革命当中,感受时代的浪潮。
二.新的希望
虽然币乎才上线了两三个月的时间,但是已经产生了很多大V级人物,每天也有好几千篇新文章的产生,覆盖了区块链的方方面面。而小Co会结合自己的背景,选择尽量与编程有所结合的方向和内容,用直白的语言、浅显易懂的逻辑,向大家阐述区块链相关的技术和原理,让更多的人能够了解到区块链技术在你看不到的地方究竟在做些什么。为了使大家感受到更好的互动性,小Co写文章会采用两人问答的形式,逐渐递进,层层剖析一个主题。当然,也欢迎大家以问答的形式在评论区互动,小Co会挑选有意思的问题和观点,在下一篇文章中,进行讨论。
小Co的愿景是,在未来往回看,小Co所写的文章,能形成一条锁链,记录小Co的区块链成长之路。也希望将来的某个时间点,有另外一个小白看到小Co的文章之后,能够学习到在区块链中是怎么成长起来的。如果文章有任何错误,或者说的不到位的,热烈欢迎批评指正,相互学习才是目的。
相信接触过区块链有一段时间的人,都会眼熟一个名词“哈希”,那哈希到底是什么?在区块链中为何会有这样重要的一个地位?它是无懈可击的吗?小Co的开篇文章,就要拉上萌新小新从研究EOS Cannon社区空投糖果的算法入手,逐行代码解析,争取为读者提供每个想了解的信息。
三.新的旅途
小新:小Co,你知道EOS Cannon的社区要空投糖果了吗?听说第一名可以得到5000EOS币呢。我也有一个奖券号。哎,可是我的号码,已经排到好几万号了,是不是这样的获奖几率就比奖券号小的要低了很多啊?
小Co:哈哈!圈内人谁不知道这个消息?5000EOS币,可是相当于人民币几十万呢,这可是一个超级大奖,而且社区不是已经说了吗,获奖机会人人平等,算法都已经公布出来了,难道你还有怀疑?
小新:额,算法我又看不懂!!(其实根本没点开过),对了,你不是做什么软件开发的吗?平时找你修电脑,总是推三阻四,今天给你一个证明自己的机会,把这个算法一五一十的解释给我这个普通人听,而且要听懂!!我才相信。
小Co:好好好,服了你了。。那点破事还搬出来,那我就勉为其难的,一行行的,解释给你听吧,让你也感受下代码的魅力。首先打开文章中的链接——算法链接,看到了吧,这一页代码就是计算中奖号的过程,是用python语言写的,什么是python自己百度。现在这个python语言,非常流行,也是外行人接触编程很好的一个选择。不过现在你只需要知道用这个语言写的东西(程序),可以让电脑识别,来执行我们想要的计算,就比如现在这个活动。
小新:这些英文单词,拆开来看,我还认识是什么意思,组合在一起,我就两眼一抹黑了。我猜电脑做计算的时候是不是从第一行开始,一步一步执行到最后一行。
小Co:对,聪明,电脑做计算,是完全遵从逻辑和顺序的,如果写的一个程序运行的结果和你预想的不一样,不要怀疑电脑,这基本上都是你自己的问题。下面我就来逐行讲解代码,搬起你的小板凳坐好了。
第1行是干嘛的呢?我们知道电脑操作系统除了windows,还有Linux,这第一句就是说如果是用的Linux系统,电脑就该去/usr/bin目录下,找到python解释器,来执行这个python代码的计算过程。
第3、4行表示导入(import)了hashlib和OrderedDict两个python标准库提供的模块,标准库可以看成是已经python预先做好了的武器库,模块就对应是不同的武器,拿来即用。这里hashlib代表着哈希(hash)有关的一系列工具,OrderedDict表示排序字典。
小新:等等等等,说得太快,要懵b了。/usr/bin这目录是什么鬼,表示从来没见过啊。python解释器又是从哪蹦出来的?
小Co:我们平常用的Windows系统,文件夹目录是从C或D或E盘这些逐渐进入的,但是Linux不一样,它的目录是从“/”开始的,也就是所谓的根目录,以后你会接触到更多目录方面的东西。Python解释器就是电脑上装的一个应用程序,由它来帮你运行写好的python文件,就像你装好了Word和Excel,才能处理相应的文档。
小新:哦哦,原来这样。那后面导入2个模块,为什么写法还不一样。排序字典这四个字表示也看不懂。。
小Co:import+模块名字是最简单的导入写法,第4行表示从collections这个模块中导出子模块,就像武器库里有collections这个武器箱,你从武器箱里挑出了OrderedDict这把平底锅。。当然了,直接import collections也是可以的,只是你拿平底锅就能吃鸡,还在背包里放那么多没用的东西干嘛。。是吧。排序字典不是说平常查找的那个字典,而是一种数据结构,也就是一种按照特定格式存放数据的地方。在这里的排序字典,作用就是按照奖卷号得分顺序,由高到低,依次存放奖券号和对应分数的地方。是的,你没想错,在这个字典里最开头的那个奖卷号,就是得到5000EOS的人生赢家。
小新:我去,那真可是黄金宝座了啊,一定是我的!!
进制转换
小Co:呵呵。。第6行这个“AA”对应的就是你奖券号上的前2个“A”,没什么太大作用。再看第7、9行,这两行是注释,以#开头的行都是注释,就是你可以写一些描述性的文字,解释器会跳过这些注释的行,不去执行。第8行表示把比特币的区块哈希(对了,就是EOS空投那篇文章里提到的计算中奖的最重要的依据),就是括号里的一长串数字和字母,这一长串其实是16进制的数字,这里的bytes.fromhex(英文的意思也体现了它的作用)就表示把这数从16进制转化成2进制,转化完之后的结果就是block_hash了。
小新:16进制、2进制。。可我只熟悉10进制啊
函数定义
小Co:这些进制概念你百度搜下就知道是怎么回事了。第10行把total_lottery设置成100000,它表示要抽奖的奖券号总数。Ok,接下来是不是看到有def 开头的5个大段,这就是所谓的函数,紧跟在def后面的就是函数的名字,比如第一个def后面的lucky_num_from_block_hash,就是这第一个函数的函数名。函数的作用其实很简单,可以看作是一个加工厂,把输入的东西进行函数内部处理,得到想要的输出。这里每一段就是函数的定义,表示函数内部的处理过程是怎么样的。
小新:emmm... 那我猜def那一行括号里的东西就是函数输入,函数里面出现return这个单词, return的中文意思是返回,所以返回的就是函数输出?诶,等等,这5个函数里,怎么有的没有输入,有的有1个,有的有2个?最后这个dump_rewards_to_file函数怎么又没有return了?
小Co:对,括号里就是输入,输入的数量可以是任意个,多个输入用逗号隔开。return的作用就是表示这个函数应该要返回什么东西(即输出),执行完return这个函数就退出了,return后面可以什么都没有,表示函数不需要任何输出,该做的事在函数里面已经全搞定了。而函数里没有return表示函数执行完最后一行就直接结束了。记住,这里出现的5段函数代码是函数的定义,是说明该函数是怎么运行的,解释器不会直接执行函数定义,而是会跳过这些定义,执行后面的代码。等到后面的代码开始使用了这些函数,解释器就会回过头来,跳到函数里面,逐行运行。
小新:使用这些函数。。想起来了,这就叫函数调用吧,我在网上经常看到这个术语。
分数计算
小Co:是的,函数调用在程序里无处不在,正确使用函数,能让程序层次分明,结构清晰。这些函数等到被调用的时候,我再依次讲解,现在我们跟着解释器的执行,跳过了函数定义的代码,来到了文件最后。
这4行依次做了4件事情,计算空投得分情况;根据各奖券得分排序;打印分数榜;把各奖券得分情况写到一个文件里去。
小新:哇,这么简单的4行就能完成这么复杂的事情吗?感觉每一步都要有很复杂的步骤才能实现呢
小Co:对,这4行代码确实完成了这么复杂的工作,每一行的复杂工作都是通过调用函数,在函数里完成的,这也体现了函数的作用,即把复杂的处理包装起来,给其它地方使用。你想想,如果那些复杂的流程,不通过函数包装,而是直接一股脑写在这里,是不是就掩盖了程序的主要逻辑。而且包装成函数之后,还能提供给多个地方使用。