【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])

        }

    }
}

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

查看所有标签

猜你喜欢:

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

The Practice of Programming

The Practice of Programming

Brian W. Kernighan、Rob Pike / Addison-Wesley / 1999-2-14 / USD 49.99

With the same insight and authority that made their book The Unix Programming Environment a classic, Brian Kernighan and Rob Pike have written The Practice of Programming to help make individual progr......一起来看看 《The Practice of Programming》 这本书的介绍吧!

html转js在线工具
html转js在线工具

html转js在线工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

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

HEX CMYK 互转工具