00:00
那我们看一下这个代码里边,它是怎么实现的呢?代码里边,呃,刚才已经找到了,对吧,这一部分代码是在。共识这一部分对吧,Cons consensus,然后下面的e harsh,下面的consensus.go里边这一部分里边,它所谓的共识其实就包含了我们这里边所有的关于出块,区块验证,还有我们奖励机制,所有的东西都在这里了,呃,那大家可以看到,一上来他就哇定义了这么多东西。定义的,这是什么东西呢?大家看一下。Frontier block reward。这是什么?Reward,是奖励对吧?Frontier frontier,这是我们之前最初的那个版本frontier,它的奖励是什么呢?Big一个NEW5E的18次。其实就是五个以态对吧,因为它单位是尾嘛,所以后面有十的18次,所以大家看到最初设定的就是每个区块奖励是五个对吧,就在这里写定了。
01:11
那当然大家后面后面看到第二个阶段,Homestead没有一个单独的设定说明,一直沿用的是frontier,对吧,一直到什么时候呢,到拜占庭。拜占庭这里又单独定义了一个block reward是。每个区块是三个对吧。所以大家就可以看到接下来还有一个定义,君士坦丁block reward,它要剪成两个,对大家大家如果就之前还还不知道这个东西怎么来的话,大家可以看到这个代码都已经进去了,对吧?所以到时候切换这个君士坦丁堡的时候,一定是会生效的每个区块。出出的以太的奖励就是两个好,那么下面还定义了一些东西,那就是max uncles,我们说最多只能包含两个书号,为什么呢?因为这里写死了,我们的共识里边写死了它只能有两,最多是两个区,两个书框。
02:06
呃,那接下来大家可以看到,就是它有一个这个。Aloud允许的未来的time,这是什么呢?允许的,这就是什么,Max time from current time a lot for blocks。也就是说,这是我们允许的最大出块时间。大家能想到这是什么吗?15乘以T点。所以大家可以看到,这相当于就定义了我们要求的这个最大能够允许的这个下一个块出出来是是多长的这个时间。那这里其实应该跟大家说这个time.second这个我看一下啊。这个我没有专门去查过这个,这个time肯定是在咱们这个common里边了,对吧,肯定在这个里边可以查到,我现在网络不好的话,可能没有办法去去实施的啥,大家可以去查一下,因为我记得之前。
03:12
呃,看到大家的说法,其实不是15秒,是15分钟。所以大家可以去看一下,就是这个time second到底是什么。呃,那在我们这里的这个这个定义呢。但是我看一下这个可不可以直接跳过去啊。对,如果要是最大时间15秒的话,大家感觉好像这个。好像会有问题是吧。这边还是很卡啊好算了,那个我诶过来了,到里面去看一下。
04:01
大家觉得这个应该在哪里去找?这个看起来没有,没有能够很符合我们要求的东西啊。呃,这个一个一个去点的话,可能会比较浪,浪费时间,因为网络比较慢。这里好像开了。这个好像也也不是是吧,好,这个要要这会儿去找的话,可能就会比较复杂,所以啊,这个东西简单说大家看后面的注释,其实是能看到他说的是,呃,就是在这些区块被未来区块确认之前,那么最多。最多的这个时间。从当前时间开始,最多允许的时间是这个时间,所以大家目前我们目测看的话,应该是一个15秒对吧?啊,当然这个确实是跟我们直观的印象好像有点偏差,这个我们到时候再可以再去详细的看,接下来我们看它这个难度定义。
05:07
难度这里边定义了一个叫做。CA difficulty君士坦丁堡对吧?然后下面还定义了一个CA difficulty拜占庭。我们现在调用的肯定是这个对吧,那大家可以看到它后面调用的方法都是一样的。它定义的是make difficulty calculator。所以这是现在就是大都会阶段第三阶段统一用的对计算难度的一个方法,难度计算器。那后边它会传进一个值,大家能够猜到这是什么值吗?上面存了一个500万,下面传了一个300万,对,这就是难度炸弹,所以大家会看到就是君士坦丁堡这个升级之后,它的难度大量会有调整的,也就是说。
06:03
那大家觉得这个军事坦丁堡升级之后,这个难度炸弹对对我们的这个影响是什么?它变成300万变500万,这影响是什么?这个数变大了。所以是不是难度炸弹,它往上提难度的这个过程就会小一点啊,对,而且大家可以看到这个为什么叫难度炸弹呢?哦,一方面这里它是指数增长的对吧,因为这里你这个数除出来之后,那一下一下子就是二的多少次幂就出去了,另外大家还注意啊,它不是一个区块增长了之后马上。就是我这里现在比方说我的这个区块数是某一个数,我加一之后,这个马上就增长上去了,不是这个难度大战,平常是不涨的。为什么呢?因为他这里要除以10万之后取整。
07:02
这个取整,那就代表说你只要不是整个整10万个的提升。那基本上这个难度就是不变的,不是不不是基本上不变,就是难度炸弹就是不变的,对吧,因为你减了之后除以10万,那都跟没有一样,最后一取整都没有了,所以刚才我们算出来这里好像是34对吧,那你你再过十个块,你再过1万个块,照样这里还是34,但是大家可能就会想到,那我假如正好是在99999那个块上。然后我再加一个框。下一个块正好10万块的时候,那这个难度瞬间就暴涨对吧。指数增长一个块,马上瞬间就指数增长,所以把它叫做难度展弹,就是有一个接月的这种提升,所以呃,也有把它叫做冰河时期,就是说那个相当于我们就会进入突然一个这个调整之后,大家就会进入一个漫长的冰河时期,你得慢慢慢的消化这个难度,对吧,慢慢的在回暖,所以是这样一个东西,好,我们看源码里面它怎么样去做这件事情啊。
08:17
那我们就看这个这个算法了,对吧,Make difficulty calculator直接去搜一下,因为它这里不能直接跳转啊,就是这个方法。这个函数大家可以看到它会传入一个Bo delay,果然这就是我们那里定义的,对吧,炸弹的这个定定时炸弹它的这个参数。然后呢,呃,它会返回,大家注意看啊,这个这个函数函数很奇怪,很奇特。它会返回。一个函数类型对吧,返回值是一个函数类型,返回的函数类型里边有这么几个参数,一个是当前的态。当前的time对吧,还有一个是。
09:01
它的副区,副区块直接把,呃,当然这是heather对吧,就是副区块的区块头直接穿进来。呃,当然了,这个函数本身还有一个返回值,是一个病因对吧,这是整个的这一个函数的一个定义声明,接下来我们看看它到底怎么做的啊。他接下来的做法是。先有一个bomb delay from parent。这是一个什么东西呢?我们先看一眼吧。他是要帮delay。去。爆炸的这个这个参数对吧,去减一。哎,这个减一是什么东西呢?啊,这个这个好像我们也也没搞懂,那就那就先不管它了,对吧。接下来我们继续看它直接return这个function啊,这就是我们定义好的这个返回的函数类型,那么这个function里边它能去做什么事情呢?首先定义一个time time就是当前的time对吧,SET64。
10:05
然后parent time,就是parent区块头里边取出来的time时间戳拿出来,然后定义一个,就声明一个X,声明一个Y,然后给他分配这个存储空间,接下来要做的事情就来了,X sub这两个。这是在干什么?然后萨布完了之后直接除以九,大家看到了,他是不是就在干这个事儿啊,对,所以前面两个时间戳去出去去减,然后后面直接除除以九。然后接下来大家注意看,如果parent.uncle hash等于empty uncle huh。这里就去减,用一去减它,否则的话就用二去减它啊对,这就是我们这里定义的,如果要是有uncle的话,那就二去检查,没有的话就一去检它,所以大家看这里定义的这个东西怎么样去用这个函数,这就用我们这个code直接去把它描述出来啊,就是非常的有意思。
11:12
然后接下来这就说了。X的compare这个这个是在干什么,这是要跟后面这个数比,对吧,MINUS99,那如果它比MINUS99小于零,那就是小,对吧。它比MINUS99小的话怎么办呢?对,它就变成MINUS99,所以就是它跟ma负99取取最大的对吧?我们的max函数就是用这种方式实现,好,那接下来我们再看,呃,刚刚才这是X,那还有个Y呢,Y干什么呢?那大家其实想到了X是在算后边的这一坨对吧?那Y是不是就就可以做前面的这一块了,那看一下果然WHY是parent的difficulty。
12:00
负区块的难度去除以difficulty帮的device,我们看一下这是个什么鬼。对哦,它是在parents里面定义的啊,这个我们还得退出去看啊,瞄一眼啊,这个可能会有点慢,大家其实可以想象得到它是什么东西,对吧?啊,上面其实有注释的对吧?这个把很多公式都已经注释在上面了,所以大家一眼就能看得出来,所以它就是除以2048,这个是一个定义的常数,在per里边定义的常数,然后呢,就用这个Y减去X乘以X。就是我们那个公式定义出来的之后,再加上。副区块的难度,那大家可以看到这是不是就已经是前面这两步了,副区块难度加上难度调整了已经有了对吧?那最后就是难度炸弹,我们看一下这个难度炸弹是怎么算的啊。呃,这里有一个。
13:02
哦,大家注意这里有一个他要去先算一下这个X。F,跟谁比呢?跟parameter里边设好的这个minimum difficulty。这是什么东西?创世块的难度大家还记得吗?在。大家还记得这个黄皮书吗?黄皮书里边定义了,对它有一个下限地零。如果要是说你比这个D0小的话,那还得选D0对不对,所以其实是不能比D0小的,那后面这个定义大家其实已经看出来了,这是什么东西呢?P是parent嘛,那PHD那其实就是parent的头里边的那个难度系数对吧?Parent难度系数加上一个X乘这个,那大家想肯定就是难度调整了对吧,最后就是。就是难度炸弹,所以黄皮书,这其实都是黄皮书里面定义好的,大家看这个X是不是除以2048。
14:05
然后之后的这一个系数是不是要跟负99取一个最大值,它这里面去除九对吧?然后这里的Y还定义了,如果说他的那个uncle是零的话,就取取一,如果不是一有uncle的话,就取二。那后边这个难度系数是什么呢?难度系数就是这个难度炸弹是上面的这个东西,它要减去300万。减去300万之后,再除以10万,减去二,然后二的这么多次方,大家看是不是就是黄皮书里面定义好的这些东西,然后在代码里边完整的实现出来,所以我们直接看黄皮书可能真是看不懂,对吧?这这一堆这个鬼,这是什么玩意儿啊?但事实上看代码的话会发现。啊,它其实很简单,其实就就这么简单的一个实现对吧,那所以这里其实就是定义的我们初始块的那个难度对吧,D0不能比它小,如果说要比它小的话,那直接就把它设置set成D0。
15:10
呃,那最后就是我们所说的这个南度炸弹,这个ice age delay,它这里是叫冰河时期的这个延迟。这里大家注意啊,它这里还给了一个叫做fake block number,它定义了一个就是假的那个block number,那这个假的block number用来干什么呢?它就是用来去大家看下边是去拿着这个副区块的。Number它的区块高度去跟这个保姆delay这个炸弹炸弹给的那个延迟的值去做对比,如果比它大或者相等大于等于零的话。那这个时候就会拿就是FA block number呢,它就会等于。
16:02
Parent number去减掉这个值,也就是说什么意思呢?就是说我们暂存了一下它的这个这个数对不对,如果说它比它要小的话,减了之后我们知道那是个负的嘛。但这个负的他直接就不算了,其实对吧,他就认为这个是零了就可以了。好,那么我们接下来看,然后他把这个Facebook number给到了这个period count,就是一个时期的一个计算。呃,那它最后的这个用法是什么呢?它就会用这个东西去除以EXEXP的different period,这又是个什么鬼呢?好来看这是在这里定义的,对吧,10万。定义出来的一个10万,所以他会把我们前面算出来这个东西直接去除以10万,除完了之后呢,然后再用这里这个二对吧。他要去减去一个二,然后再用二去乘以它这么多次方。
17:05
最后跟X加起来,是不是就是我们这个计算计算公式啊。所以这就是整个难度调整的这个完整的实现,其实代码也不多,就这么目测,估计也就二三十行,四三三四十行吧,对吧。如果去了这些注释的话,我估计也就20多行,就这么简单把这个黄皮书里边大家看起来完全看不懂的东西就已经实现出来了,那那这个概念,因为呃,黄皮书里面别的概念其实我们都提到了,但是这个难度调整,这个难度炸弹,这个东西确实可能之前没跟大家说过,所以我们这里单独拿出来,而且我觉得这个例子特别好,就是结合黄皮书对吧,首先白皮书里边有一个大概的一个观点,说我们要保持这个稳定的出画速度,保证出画时间。黄皮书里边就定义了我们怎么样去保证出画时间的调整难度,然后用这种数学的这种这种这种范式啊模式把它全写出来了,有这种数学的这种这种范式写出来的话,其实就代表它确实是可以实现的,那我们看这个代码就这么简单的实现了,所以大家如果要是把这个一搞清楚的话,应该觉得还是比较有意思的,对吧?这个事情特别是大家可以根据这个用算式大家想验证的话,刚才我们真是就是手动去验证了一遍,发现一点不差,这么大的数一点不差。
18:32
对吧,一个一个数位都不差的,那大家如果不相信的话,自己下去之后再去算一算,按照我们这个甚至可以算更早之前的区块,对吧,看看他在难度调整这个规则之前,拜占庭之前,那是不是符合它的这个定义,咱可以去自己做计算啊。好,那么我们这一部分还有一点时间,我们再讲讲源码里边。我们就照着这个这个下面还有一部分东西给大家讲一点吧。
19:01
就是在这一个共识的这个文件里边呢,大家可以看到下面的就是,呃,这个计算calc cculate difficulty from frontier对吧,这就是最初的时候他怎么算难度,这是这种算法。呃,下边下边大家看very verify,这就是做那个哈西,呃,Pow的难度校验了,对吧,这就在在验证这些东西了,所以整个这就是我们的共识机制。然后他这里还有啊,这是prepare,还有final。然后这是这个这个哈希怎么去算对吧。好,我们讲一下最后这一部分就是怎么奖励吧,这个accumulated的accumul rewards对吧,他去这个,呃呃,收集累积的这个奖励,我们看一下他这是一个什么样的东西,它传入的参数传了一堆什么,什么参数呢,首先有con。啊,大家应该想到就是为什么要传conig呢?
20:03
我得先确定你你当前到底是哪个版本对不对,要不然我不知道按哪个数去讲,所以说这里是肯定要有的,然后有一个state。大家说state是干什么的?我要奖励奖励以太,那肯定要改余额对不对,肯定要改balance,那这个肯定跟状态有关,所以肯定要用到state,然后还有。那hier的话大家知道,就是我们这里边它会有这个书块啊什么的东西,对吧,引用的这些东西,那那当然了,这里就还有这个uncle,书块里面是这个header里面是有哈希的嘛,这里还有这个uncles,所以大家就会看到,呃,所有的这些参数确实都是我们计算奖励的时候应该用得着的东西,那我们就具体的看一看,它怎么算呢?首先block reward定义了一个区块奖励等于什么呢?啊,它先定义的是frontier block reward,这是我们初始的这个书号奖励对吧,五个好,接下来他就看了,嗯,那大家就会发现,那这个东西肯定是会调整的,对吧?随着config里边如果is by暂停,那么我就把这个reward改成BY暂停的block reward改成三个,对吧?现在大家一看就到这里就改成三了,而且大家看到一占庭的时候,他是怎么做的呢?
21:25
他不是说直接就写死说,哎,我现在是拜占庭了,然后你就直接给三哥就可以了,对吧,他是要去判断一下,而且是根据当前的区块高度去判断,所以它代表什么,你即使现在我们状态,大家认为现在现实的最新的状态是拜占庭了,但是你同样可以去做之前的区块要。验证对吧,你同样去可以在之前的版本上把我们的历史数据去跑一遍,你看看是不是应该给这个矿工那么多奖励,给这个书块那么多奖励,所以说如果我们这里校验的时候是校验历史数据的话,那传进来的高度就不应该是我们当前的拜占庭的高度,对吧?所以说它这里是一个动态的状状态,你根据你要判定的这个区块高度不同,会有不同的版本判定。
22:18
当然我们最新的版本当然就是走这一条分支,对吧,那下面它还会继续判断,你如果是君士坦丁堡的话,已经到了这个高度的话,那就直接给的是君士坦丁堡两个的那个区块奖励了,这是先把这个区块奖励先定下,然后接下来呢,它非常简单,Reward,定义一个set block reward。先塞进去,这就是要给矿工的一个奖励,对吧,先放这儿。然后大家就看到又定义了一个R,然后这个R有什么用呢?呃,大家看这里是一个for循环,这个循环是要把ons里边的值要遍历一遍,对吧?对,大家应该熟悉go里边的语法啊,Range这个是代表便利的,For里边的便利,然后r.ADD那就是先把这个number。
23:10
要加上八。Uncle的这个number要加上八。方口的区块高度加八。这是要干嘛呢?我们继续往后看吧。然后又减对吧。刚才加了八,现在再减,减谁呢?减去当前的区块高度。所以大家想到这是在干什么了吗?我们之前说过,书块的奖励应该是当前区块奖励的多少来着,一般是7/8对吧,7/8个区块奖励。那对,7/8说的是自己亲叔叔,也就是只比自己当前区块高度低一个,少一,那就是亲叔叔对吧?那么他加八之后,再减当前的这个高度是不是就变成七了?对,所以大家就可以看到跟他的区号高度有关,你如果离得再远一辈的话,如果是叔爷爷的话,那减完了之后就剩六了,对吧?所以我们的区块奖励就变成6/8对不对?
24:17
好,那我们看是不是这样做啊,果然后边直接就拿这个这个数就乘以区块奖励,再除以八,所以是不是就是7/8或者6/8 5/8这样的一个奖励。好,那所以整个的这一个R大家看就会直接加到state.at balance,这是状态的一个方法,对吧,就直接改状态里面的balance了,改谁的balance呢?uncle.coin base uncle是一个区块,他的这个块挖他的那个coin bases直接讲给他。这就是书块奖励对不对?好,然后后边大家还可以看到,还有一部分。
25:01
R。他还要再去去去变成一个什么东西呢?是当前的区块奖励除以32,再给到R去,这是什么东西呢?1/32的区块奖励,大家还记得吗?对,书块引用奖励对吧?因为我们这里既然你能查到这个有效的书块,前面如果我们已都已经验证了的话,那当然它就是有效的,所以你既然引用了,那这1/32给你,所以大家看reward.addadd上这个R,那reward是前面我们已经给了区块奖励的这一部分,对不对?已经给了三个了,然后再给上三个的1/32。嗯。所以大家看到最后stand at balance head coin base,那是我们当前这个块的coin base,把这个加进去,所有的区块奖励不算进去了。当然大家可以啊,有些同学可能想到,那你这个跟我们当时看的这个这个不一样啊,他后面不是还有一个transaction fee吗?啊,那个不是在这里算的那个是啊,GA手续费,那是另外一套计算机制,对吧?那跟里边的这个交易所有的整个的这个去去计算gas这个相关,我们这里就是整个区块奖励的一个计算,所以大家看到这里也是啊,就这么十几十几20行的一个代码,就把我们之前给大家说过的,就是幽灵协议里边定义好的,怎么样给区块做奖励,对吧?把这些东西就都完成了。
26:35
好,这就是我们整个这个以太坊在做这个难度调整和共识机制里边区块奖励这一部分的源码的一个分析和实现,所以大家如果感兴趣,真的是可以就是对着这个黄皮书先看一看,发现黄皮书看不懂,然后有可能我们找到对应的代码之后,然后一看发现,哦,原来是这么回事啊。
27:00
这黄皮书是写的很数学范,很这个论文范。那代码里边其实是很清晰的,把它一点一点都实现出来。好,那我们本来我计划是还想给大家把这个黄皮书,就是前面我们这个交易啊,还有盖啊,这个细细的过一下,但是我觉得就一方面大家可能也。不是特别的感兴趣对吧,比较枯燥无味,另外一方面,确实这些东西大家其其实之前都给大家讲过,所以说就是大家也也不是那么的陌生,所以说这些东西至少概念都知道嘛,大家就不用再去细细的看了,但是关于这一个就像这个难度调整,这个难度炸弹这个东西可能比较有意思,说不准以后出去之后有人会问你这个问题啊,所以我觉得讲一下还是有必要的,也比较好玩。
我来说两句