DPOS共識演演算法實現(Golang版)
阿新 • • 發佈:2019-12-31
DPOS原理
DPOS全稱Delegated proof of Stake,中文是委託權益證明。
可以理解為整個區塊鏈網路有許多節點,我們需要選出一些節點作為代表來維護整個區塊鏈網路,這些代表需要保證區塊鏈的安全和效能,不需要通過POS算力競爭了,節約能源。
DPOS規則
他們可以生產區塊,如果不稱職就會被踢出代表列表重新選舉。這裡的選舉最少需要整個網路一半的節點通過則證明去中心化的有效投票。
DPOS演演算法要求隨機指定代表列表的順序,不按照順序生成區塊的是無效的,每個週期會重新洗牌一次,打亂原有順序。代表之間不存在爭奪情況,不會遺漏區塊,定時會出現一個區塊,這就使共識達成的時間週期大大縮短,這也是相對於POS,POW的優點所在。
DPOS獎勵機制
DPOS因為每秒可以處理確認比POW和POS大上幾個數量級的交易量,會將一部分交易作為獎勵給網路維護節點和投票者,作為代表選舉維護的獎勵,讓更多的節點參與進來。
Golang實現DPOS演演算法
包引入
package main
import (
"crypto/sha256"
"encoding/hex"
"fmt"
"math/rand"
"sort"
"time"
)
複製程式碼
區塊結構體定義
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
fmt.Println("NewBlock: " ,newBlock)
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)
fmt.Println("NewHash: ",hex.EncodeToString(hash))
return hex.EncodeToString(hash)
}
複製程式碼
檢查新區塊是否合法
func isBlockValid(newBlock,oldBlock Block) bool{
if oldBlock.Index + 1 != newBlock.Index{
fmt.Println("失敗!!index非法")
return false
}
if newBlock.PrevHash != oldBlock.Hash{
fmt.Println("失敗!!PrevHash非法")
return false
}
fmt.Println("合法")
return true
}
複製程式碼
定義區塊鏈,代表,代表列表
var blockChain []Block
type Trustee struct{
name string
votes int
}
type trusteeList [] Trustee
複製程式碼
代表排序
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
}
複製程式碼
代表列表生成
func selecTrustee()([]Trustee){
_trusteeList := []Trustee{
{"node1",rand.Intn(100)},{"node2",{"node3",{"node4",{"node5",{"node6",{"node7",{"node8",{"node9",{"node10",{"node11",{"node12",}
sort.Sort(trusteeList(_trusteeList))
result := _trusteeList[:5]
_trusteeList = result[1:]
_trusteeList = append(_trusteeList,result[0])
fmt.Println("當前超級節點代表列表是:",_trusteeList)
return _trusteeList
}
複製程式碼
main函式部分
func main(){
t := time.Now()
//模擬創世塊的生成,實際要複雜一些
genesisBlock := Block{0,t.String(),createBlockHash(Block{}),"",""}
fmt.Println("創世塊block: ",genesisBlock)
blockChain = append(blockChain,genesisBlock)
var trustee Trustee
for _,trustee = range selecTrustee(){
_BPM := rand.Intn(100)
blockHeight := len(blockChain)
oldBlock := blockChain[blockHeight-1]
newBlock,err := generateBlock(oldBlock,_BPM,trustee.name)
if err!=nil{
fmt.Println("新生成區塊失敗:",err)
continue
}
if isBlockValid(newBlock,oldBlock){
blockChain = append(blockChain,newBlock)
fmt.Println("當前操作區塊節點為:",trustee.name)
fmt.Println("當前區塊數:",len(blockChain))
fmt.Println("當前區塊資訊:",blockChain[len(blockChain)-1])
}
}
}
複製程式碼
執行截圖
結尾
大家也可以試試,區塊鏈還是很有意思的啊~~~~~