【go共识算法】-DPOS

栏目: Go · 发布时间: 6年前

内容简介:Delegated Proof of Stake,委任权益证明。中文名叫做股份授权证明机制(又称受托人机制),它的原理是让每一个持有比特股的人进行投票,由此产生101位代表 , 我们可以将其理解为101个超级节点或者矿池,而这101个超级节点彼此的权利是完全相等的。从某种角度来看,DPOS有点像是议会制度或人民代表大会制度。如果代表不能履行他们的职责(当轮到他们时,没能生成区块),他们会被除名,网络会选出新的超级节点来取代他们。DPOS的出现最主要还是因为矿机的产生,大量的算力在不了解也不关心比特币的人身

DPOS介绍

概念

Delegated Proof of Stake,委任权益证明。

中文名叫做股份授权证明机制(又称受托人机制),它的原理是让每一个持有比特股的人进行投票,由此产生101位代表 , 我们可以将其理解为101个超级节点或者矿池,而这101个超级节点彼此的权利是完全相等的。从某种角度来看,DPOS有点像是议会制度或人民代表大会制度。如果代表不能履行他们的职责(当轮到他们时,没能生成区块),他们会被除名,网络会选出新的超级节点来取代他们。DPOS的出现最主要还是因为矿机的产生,大量的算力在不了解也不关心比特币的人身上,类似演唱会的黄牛,大量囤票而丝毫不关心演唱会的内容。

比特股引入了见证人这个概念,见证人可以生成区块,每一个持有比特股的人都可以投票选举见证人。得到总同意票数中的前N个(N通常定义为101)候选者可以当选为见证人,当选见证人的个数(N)需满足:至少一半的参与投票者相信N已经充分地去中心化。

见证人的候选名单每个维护周期(1天)更新一次。见证人然后随机排列,每个见证人按序有2秒的权限时间生成区块,若见证人在给定的时间片不能生成区块,区块生成权限交给下一个时间片对应的见证人。DPoS的这种设计使得区块的生成更为快速,也更加节能。

DPoS充分利用了持股人的投票,以公平民主的方式达成共识,他们投票选出的N个见证人,可以视为N个矿池,而这N个矿池彼此的权利是完全相等的。持股人可以随时通过投票更换这些见证人(矿池),只要他们提供的算力不稳定,计算机宕机,或者试图利用手中的权力作恶。

应用

  • 比特股 Bitshares(提出这个概念)
  • EOS

共识算法我DPoS + BFT

  • Asch

共识算法为DPoS + PBFT, 有101个受托人, 目前正在开放竞选

go实现DPOS

package main

import (
    "time"
    "encoding/hex"
    "math/rand"
    "log"
    "sort"
    "crypto/sha256"
)
//定义区块结构体
type Block struct {
    Index int
    Timestamp string
    BPM int
    Hash string
    PrevHash string
    Delegate string
}
// 创建区块函数
func generateBlock(oldBlock Block, _BMP int, address string) (Block, error) {
    var newBlock Block
    t := time.Now()

    newBlock.Index = oldBlock.Index + 1
    newBlock.Timestamp = t.String()
    newBlock.BPM = _BMP
    newBlock.PrevHash = oldBlock.Hash
    newBlock.Hash = createBlockHash(newBlock)
    newBlock.Delegate = address

    return newBlock, nil
}
//生成区块hash
func createBlockHash(block Block) string {
    record := string(block.Index) + block.Timestamp + string(block.BPM) + block.PrevHash
    sha3 := sha256.New()
    sha3.Write([] byte(record))
    hash := sha3.Sum(nil)
    return hex.EncodeToString(hash)
}
// 简单的检验区块函数
func isBlockValid(newBlock, oldBlock Block) bool{
    if oldBlock.Index + 1 != newBlock.Index {
        return false
    }

    if newBlock.PrevHash != oldBlock.Hash {
        return false
    }
    return true
}
// 区块集合
var blockChain []Block

// dpos里的超级节点结构体(受托人)
type Trustee struct {
    name string
    votes int
}

type trusteeList [] Trustee
// 下面的三个函数是为了 排序 使用,大家可以查下 go 的排序还是很强大的
func (_trusteeList trusteeList) Len() int {
    return len(_trusteeList)
}
func (_trusteeList trusteeList) Swap(i, j int){
    _trusteeList[i], _trusteeList[j] = _trusteeList[j], _trusteeList[i]
}
func (_trusteeList trusteeList) Less(i, j int) bool {
    return _trusteeList[j].votes < _trusteeList[i].votes
}

// 选举获得投票数最高的前5节点作为超级节点,并打乱其顺序
func selectTrustee() ([]Trustee){
    _trusteeList := [] Trustee {
        {"node1", rand.Intn(100)},
        {"node2", rand.Intn(100)},
        {"node3", rand.Intn(100)},
        {"node4", rand.Intn(100)},
        {"node5", rand.Intn(100)},
        {"node6", rand.Intn(100)},
        {"node7", rand.Intn(100)},
        {"node8", rand.Intn(100)},
        {"node9", rand.Intn(100)},
        {"node10", rand.Intn(100)},
        {"node11", rand.Intn(100)},
        {"node12", rand.Intn(100)},
    }
    sort.Sort(trusteeList(_trusteeList))
    result := _trusteeList[:5]
    _trusteeList = result[1:]
    _trusteeList = append(_trusteeList, result[0])
    log.Println("当前超级节点列表是", _trusteeList)
    return _trusteeList
}

func main() {
    t := time.Now()

    // init gensis block(创建创世块,真正的可不是这么简单的,这里只做流程实现)
    genesisBlock := Block{0, t.String(), 0, createBlockHash(Block{}), "", ""}
    blockChain = append(blockChain, genesisBlock) // 这里只是完成了一次dpos的写区块操作,eos真正的是每个节点实现6个区块,并且所有超级节点(21个)轮完,之后再做选举
    var trustee Trustee
    for _, trustee = range selectTrustee() {
        _BPM := rand.Intn(100)
        blockHeight := len(blockChain)
        oldBlock := blockChain[blockHeight - 1]
        newBlock, err := generateBlock(oldBlock, _BPM, trustee.name)
        if err != nil {
            log.Println(err)
            continue
        }

        if isBlockValid(newBlock, oldBlock) {
            blockChain = append(blockChain, newBlock)
            log.Println("当前操作区块的节点是: ", trustee.name)
            log.Println("当前区块数量是: ", len(blockChain) - 1)
            log.Println("当前区块信息: ", blockChain[len(blockChain) - 1])

        }

    }
}

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

数据驱动设计

数据驱动设计

[美]罗谢尔·肯(RochelleKing)、[美]伊丽莎白F.邱吉尔(Elizabeth F Churchill)、Caitlin Tan / 傅婕 / 机械工业出版社 / 2018-8 / 69.00元

本书旨在帮你了解数据引导设计的基本原则,了解数据与设计流程整合的价值,避免常见的陷阱与误区。本书重点关注定量实验与A/B测试,因为我们发现,数据分析与设计实践在此鲜有交集,但相对的潜在价值与机会缺大。本书提供了一些关于在组织中开展数据实践的观点。通过阅读这本书,你将转变你的团队的工作方式,从数据中获得大收益。后希望你可以在衡量指标的选择、佳展示方式与展示时机、测试以及设计意图增强方面,自信地表达自......一起来看看 《数据驱动设计》 这本书的介绍吧!

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具