共识算法是区块链非常重要的一种算法,简单来说,共识算法就是为了使网络中的节点得到一致的认可。就比如说合作双方达成一致,共同遵守某个合约。

传统的分布式系统中,由于有着中心服务器进行统一管理,各个子服务器只需要跟着中心服务器进行操作即可。而区块链作为一种去中心化分布式系统,并没有传统意义上的中心服务器,因此传统的分布一致性算法并不适用于区块链网络。每个服务器都可以是中心服务器,那么这样就需要一种新的算法来维护系统中的一致性了。现在区块链中,主流的共识算法一般为三种:POW,POS和DPOS。

工作量证明(Proof Of Work)

工作量证明算法之前已经提到过,在实现微型区块链时用的就是pow算法,这是最传统最经典的共识算法,应用在比特币中。它的原理就是寻找一个以若干个0为开头的哈希串。举个例子,给定字符串“blockchain”,我们给出的工作量要求是,可以在这个字符串后面连接一个称为nonce的整数值串,对连接后的字符串进行sha256哈希运算,如果得到的哈希结果(以十六进制的形式表示)是以若干个0开头的,则验证通过。为了达到这个工作量证明的目标,我们需要不停地递增nonce值,对得到的新字符串进行sha256哈希运算。

原理非常的简单,也可以说是只需要算就行了。

这样也存在一个问题,那就是它只要求算力,不要求理解区块链的本身,也就造成了现如今比特币的大量矿机无脑挖矿。就像演唱会的黄牛,买票只为了获取它的利益,并不在意演唱会本身的内容。为了避免这种靠纯运算的共识机制,相继提出来很多新的共识算法。

权益证明(Proof Of Stake)

今天重点讲讲POS机制。

权益证明,它提出来币龄的概念,币龄 = 持有的货币数 * 持有时间,比如说我有100币,持有了30天,那么我的币龄就是3000。币龄越大的节点呢获取记账权(也就是生成区块)的概率越大。每次记完账之后,该节点的币龄就清空。当然,刚获取的币不能直接参与币龄计算,一般是30天之后开始计算币龄。

那么这样会产生一个问题:囤币来获取绝对记账权。为了防止这种情况发生,会设置一个最大概率,一般设置90天时获得最大记账概率,之后不再增加。

但是POS本质上还是类似POW的暴力计算,只不过币多的人更有可能挖到矿,降低了POW的全网一致难度,谁算力强谁记账的局限性。

具体来看代码怎么实现它的吧:


导入所需包:

package mainimport ("bytes""crypto/sha256""encoding/binary""fmt""math""math/big""math/rand""time"
)

定义常量设置最大最小概率,这里由于不可能等30天之后再计算币龄,我设置10秒之后开始计算,并且防止数据过大,按分钟计时:

const (dif         = 2INT64_MAX   = math.MaxInt64MaxProbably = 255MinProbably = 235MaxCoinAge  = 10Minute      = 60
)

定义币的数据结构和一个币池,这里币中提出了地址Address概念,一般理解为钱包地址,一般一个钱包属于一个用户,表明这个币的所有权是这个地址对应的用户:

type Coin struct {Time    int64Num     intAddress string
}var CoinPool []Coin

定义区块和链:

type Block struct {PrevHash  []byteHash      []byteData      stringHeight    int64Timestamp int64Coin      CoinNonce     intDif       int64
}type BlockChain struct {Blocks []Block
}

init函数,设置随机数种子和币池初始化,会在main函数开始前自动执行:

func init() {rand.Seed(time.Now().UnixNano())CoinPool = make([]Coin, 0)
}

生成创世块,传入的参数是区块上的数据data和挖矿地址addr,这里每个区块的币随机给出1到5,币池增加创世块的币:

func GenesisBlock(data string, addr string) *BlockChain {var bc BlockChainbc.Blocks = make([]Block, 1)newCoin := Coin{Time:    time.Now().Unix(),Num:     1 + rand.Intn(5),Address: addr,}bc.Blocks[0] = Block{PrevHash:  []byte(""),Data:      data,Height:    1,Timestamp: time.Now().Unix(),Coin:      newCoin,Nonce:     0,}bc.Blocks[0].Hash, bc.Blocks[0].Nonce, bc.Blocks[0].Dif = ProofOfStake(dif, addr, bc.Blocks[0])CoinPool = append(CoinPool, newCoin)return &bc
}

生成新区块函数,还是一样,prevHash对应上一个节点的Hash,随机给出1-5币奖励,记录该币的所有者地址addr,币池增加新区块的币:

func GenerateBlock(bc *BlockChain, data string, addr string) {prevBlock := bc.Blocks[len(bc.Blocks)-1]newCoin := Coin{Time:    time.Now().Unix(),Num:     1 + rand.Intn(5),Address: addr,}b := Block{PrevHash:  prevBlock.Hash,Data:      data,Height:    prevBlock.Height + 1,Timestamp: time.Now().Unix(),}b.Hash, b.Nonce, b.Dif = ProofOfStake(dif, addr, b)b.Coin = newCoinbc.Blocks = append(bc.Blocks, b)CoinPool = append(CoinPool, newCoin)
}

权益证明算法:

POS机制的核心算法了,设置的是10s之后开始计算币龄,根据币龄coinAge调整当前难度Dif以获取真实难度realDif。挖矿还是类似POW寻找一个nonce加在尾部,寻找到第一个满足真实难度realDif的sha256哈希串:

func IntToHex(num int64) []byte {buff := new(bytes.Buffer)err := binary.Write(buff, binary.BigEndian, num)if err != nil {panic(err)}return buff.Bytes()
}func ProofOfStake(dif int, addr string, b Block) ([]byte, int, int64) {var coinAge int64var realDif int64realDif = int64(MinProbably)curTime := time.Now().Unix()for k, i := range CoinPool {if i.Address == addr && i.Time+MaxCoinAge < curTime {//币龄增加, 并设置上限var curCoinAge int64if curTime-i.Time < 3*MaxCoinAge {curCoinAge = curTime - i.Time} else {curCoinAge = 3 * MaxCoinAge}coinAge += int64(i.Num) * curCoinAge//参与挖矿的币龄置为0CoinPool[k].Time = curTime}}if realDif+int64(dif)*coinAge/Minute > int64(MaxProbably) {realDif = MaxProbably} else {realDif += int64(dif) * coinAge / Minute}target := big.NewInt(1)target.Lsh(target, uint(realDif))nonce := 0for ; nonce < INT64_MAX; nonce++ {check := bytes.Join([][]byte{b.PrevHash,[]byte(b.Data),IntToHex(b.Height),IntToHex(b.Timestamp),IntToHex(int64(nonce)),},[]byte{})hash := sha256.Sum256(check)var hashInt big.InthashInt.SetBytes(hash[:])if hashInt.Cmp(target) == -1 {return hash[:], nonce, 255 - realDif}}return []byte(""), -1, 255 - realDif
}

再写个打印区块和打印币池函数:

func Print(bc *BlockChain) {for _, i := range bc.Blocks {fmt.Printf("PrevHash: %x\n", i.PrevHash)fmt.Printf("Hash: %x\n", i.Hash)fmt.Println("Block's Data: ", i.Data)fmt.Println("Current Height: ", i.Height)fmt.Println("Timestamp: ", i.Timestamp)fmt.Println("Nonce: ", i.Nonce)fmt.Println("Dif: ", i.Dif)}
}func PrintCoinPool() {for _, i := range CoinPool {fmt.Println("Coin's Num: ", i.Num)fmt.Println("Coin's Time: ", i.Time)fmt.Println("Coin's Owner: ", i.Address)}
}

写个main函数测试看看,虚拟两个地址,当然啊真实区块链的地址不可能这么简单,需要使用公钥生成地址算法。

给addr1先记账,获取一定币,等待可以计算币龄时再次记账,再给新地址addr2记账,看看难度对比:

func main() {addr1 := "192.168.1.1"addr2 := "192.168.1.2"bc := GenesisBlock("reigns", addr1)GenerateBlock(bc, "send 1$ to alice", addr1)GenerateBlock(bc, "send 1$ to bob", addr1)GenerateBlock(bc, "send 2$ to alice", addr1)time.Sleep(11 * time.Second)GenerateBlock(bc, "send 3$ to alice", addr1)GenerateBlock(bc, "send 4$ to alice", addr2)Print(bc)PrintCoinPool()
}

看看打印结果吧:

可以看到啊,addr1记前四笔账的时候难度都是20,第五笔的时候,由于之前延迟了11秒,开始计算币龄,难度减小到了15,第六笔账由addr2记账,难度又回到了20,同时看币池,参与币龄计算的币的Time统一到第5笔记账时间,也就是刷新了币龄。

当然啊,真实环境中肯定不是顺序记账,每个节点都会竞争记账权,最先计算出满足难度的hash串的节点优先记账,并向全网广播,开始下一次记账权争夺。

好了,今天到这里了~下次讲讲更有效率的共识算法,也是三大主流算法的最后一个:DPOS。

如果对区块链感兴趣,可以关注下面这个公众号哦,推送的全是区块链干货~

这可能是全网最简单的POS共识机制算法相关推荐

  1. pos共识机制_OK区块链60讲 | 第17集:什么是PoS共识机制

    什么是PoS共识机制https://www.zhihu.com/video/1196092110837805056 <OK区块链60讲>是由OKEx&新浪科技联合出品的区块链科普动 ...

  2. POS共识机制竟然漏洞这么多 | 分析POS共识机制的原理带来的思考

    序言 上文深入比特币.以太坊源码带你解读POW共识机制我们学习探讨了POW共识机制,看完得童鞋们应该就知道POW是有几大缺点的:出块慢,共识时间长.开销大等等,那么有没有其它的共识机制能够解决这些问题 ...

  3. 通俗讲解:PoW共识机制与以太坊的关系、Ghost协议 及 Casper PoS共识机制的变种...

    作者:林冠宏 / 指尖下的幽灵 掘金:juejin.im/user/587f0d- 博客:www.cnblogs.com/linguanh/ GitHub : github.com/af9133374 ...

  4. 通俗讲解:PoW共识机制与以太坊的关系、Ghost协议 及 PoS共识机制的变种---Casper...

    作者:林冠宏 / 指尖下的幽灵 掘金:https://juejin.im/user/587f0dfe128fe100570ce2d8 博客:http://www.cnblogs.com/linguan ...

  5. pos共识机制_PoS共识机制是什么?其优缺点分别是什么?

    PoS共识机制的全称是Proof of Stake.PoS机制通过计算每个节点所占代币的比例和时间,等比例的降低挖矿难度,从而加快找随机数的速度.以太坊采用的PoS则是Casper投注共识,通过保证金 ...

  6. 以太坊的POS共识机制(二)理解 Serenity :Casper

    Original post by Vitalik Buterin, on December 28th, 2015 特别感谢Vlad Zamfir,他提出了按块达成共识这个想法,并且说服我认同它和Cas ...

  7. go语言实现PoS共识机制

    1.新建main.go文件 package mainimport ("bufio""crypto/sha256""encoding/hex" ...

  8. 区块链共识机制:POW、POS、DPOS、PBFT、POOL

    共识机制作为区块链的关键技术之一,在业务吞吐量.交易速度.不可篡改性.准入门槛等等方面发挥重要的作用. 区块链是去中心化的,没有中心记账节点,所以需要全网对账本达成共识.目前有POW.POS.DPOS ...

  9. 区块链共识机制技术二——POS(权益证明)共识机制

    前言 由于区块链是去中心化分散网络,所以必须设计一套维护系统的运作顺序和公平性的机制,即共识机制,用来决定谁取得区块链的记账权并获得系统新币奖励.比特币的POW共识机制是一种多劳多得的模式,其优点是算 ...

最新文章

  1. Mac Os 基本命令行
  2. python壁纸4k_【python日常学习】爬取4K桌面壁纸
  3. text-size-adjust: none并没有什么用
  4. php post nginx 400,Nginx静态文件响应POST请求 提示405错误的解决方法
  5. 【渝粤教育】国家开放大学2018年秋季 0630-21T环境法学 参考试题
  6. Axios的Vue插件(添加全局请求/响应拦截器)
  7. CentOS 6快捷安装RabbitMQ教程
  8. git管理工具_使用包管理工具
  9. 滑动窗口算法_从一道题讲解滑动窗口算法该如何实现
  10. JavaScript 事件相关
  11. python的类和对象例题_Python类、类对象和实例对象、组合、绑定详细讲解
  12. 红外遥控NEC协议总结
  13. 程序的静态链接,动态链接和装载
  14. hping 详解_hping3使用
  15. android 截屏分享权限,android 截屏+保存图片+权限
  16. 实践小笔记(1) --- DBSCAN
  17. springboot疫情防控下基于微信小程序的食堂订餐系统毕业设计源码261620
  18. 女友的生日礼物能随便嘛?Python小妙招:制作一款出圈九宫格抽奖小程序。
  19. python走迷宫_Python使用Tkinter实现机器人走迷宫
  20. CrowdHuman数据集转成VOC格式并训练模型

热门文章

  1. 【LatinIME】默认开启键盘按键声
  2. 杠杆交易的优势是什么?
  3. 【AI每日播报】亚马逊发布多项AI云服务 魅族初试人工智能化系统
  4. 机器学习:优化算法Optimizer比较和总结(SGD/BGD/MBGD/Momentum/Adadelta/Adam/RMSprop)
  5. 使用js来修改css文件来动态隐藏元素
  6. Mysql 命令行模式访问操作mysql数据库
  7. taskflow以任务节点启动任务
  8. 3ds Max随堂笔记 复制方式与基本体建模
  9. tcpdump命令使用方法
  10. LM详解 Bert系 论文译读