- PoW(Proof of Work:工作量证明),以BTC为代表,区块链1.0
- PoP(Proof of Stake:股权证明),以ETH为代表,区块链2.0
- DPoS(Decentralized Proof of Stake:去中心化的股权证明):以EOS为代表,区块链3.0
PoW
优点
- 难度系数(difficulty)可自动调整
- 越早进场,越占优势,有促进作用
- 奖励都是分给个人,相对公平,相对去中心化
缺点
- 对资源消耗大
- 比的是算力,谁算力大,谁占优势,以去中心化有所违背
- 安全性还差点意思,“51%算力攻击”
PoS
优点
缺点
- 攻击成本低,节点有token可以发起脏数据的区块攻击
以下就是这三个共识算法的伪代码 数据结构:model.Block.go
package model
type PowBlock struct {
Index int64
Timestamp string
Hash string
PrevHash string
NodeAddress string
Data string
Nonce int
}
type PosBlock struct {
Index int64
Timestamp string
Hash string
PrevHash string
NodeAddress string
Data string
Nonce int
}
type DPosBlock struct {
Index int64
Timestamp string
Hash string
PrevHash string
NodeAddress string
Data string
Nonce int
}
type WitnessNode struct {
Name string
NodeAddress string
Votes int
}
全局变量:common/globleValue.go
package common
import (
"block_test/model"
)
var PowGlobleBlocks []model.PowBlock
var PowCandidateBlocks []model.PowBlock
var PosGlobleBlocks []model.PosBlock
var PosCandidateBlocks []model.PosBlock
var StackRecord []string
var WitnessList []model.WitnessNode
var BeforeTime int64
var DPosCycle = 60 * 60
var WitnessNum = 100
PoW伪代码:server/pow.go
package server
import (
"block_test/common"
"block_test/model"
"encoding/hex"
"math/rand"
"strconv"
"strings"
"time"
)
func IsBlockHashMatchDifficulty(block model.PowBlock, difficulty int) bool {
prefix := strings.Repeat("0", difficulty)
hash := powCalculateHash(block)
return strings.HasPrefix(hash, prefix)
}
func powCalculateHash(block model.PowBlock) string {
return "hash"
}
func PowGenerateBolck(oldBlock model.PowBlock, data string, difficulty int) model.PowBlock {
var newBlock model.PowBlock
newBlock.Timestamp = strconv.FormatInt(time.Now().Unix(), 10)
newBlock.Index = oldBlock.Index + 1
newBlock.Data = data
newBlock.PrevHash = oldBlock.Hash
for i := 0; ; i++ {
newBlock.Nonce = hex.EncodedLen(rand.Intn(255))
newBlock.Hash = powCalculateHash(newBlock)
if IsBlockHashMatchDifficulty(newBlock, difficulty) {
common.PowCandidateBlocks = append(common.PowCandidateBlocks, newBlock)
break
}
}
return newBlock
}
func VerifyBlock(difficulty int) {
var resultBlock model.PowBlock
for i := 0; i < len(common.PowCandidateBlocks); i++ {
if IsBlockHashMatchDifficulty(common.PowCandidateBlocks[i], difficulty) {
resultBlock = common.PowCandidateBlocks[i]
break
}
continue
}
common.PowGlobleBlocks = append(common.PowGlobleBlocks, resultBlock)
}
PoS伪代码:server/pos.go
package server
import (
"block_test/common"
"block_test/model"
"math/rand"
"strconv"
"time"
)
func posCalculateHash(block model.PosBlock) string {
return "hash"
}
func getCoinBlance(nodeAddress string) int {
balance := 5
return balance
}
func stackRecordContainNodeAddress(stackRecord []string, nodeAddress string) bool {
for i := 0; i < len(stackRecord); i++ {
if stackRecord[i] == nodeAddress {
return true
}
}
return false
}
func StakeDistribution() {
var stackRecord []string
for i := 0; i < len(common.PosCandidateBlocks); i++ {
nodeAddress := common.PosCandidateBlocks[i].NodeAddress
coinNum := getCoinBlance(nodeAddress)
for j := 0; j < coinNum; j++ {
if stackRecordContainNodeAddress(stackRecord, nodeAddress) {
break
}
stackRecord = append(stackRecord, nodeAddress)
}
}
common.StackRecord = stackRecord
}
func StakeDistribution2() {
var stackRecord []string
for i := 0; i < len(common.PosCandidateBlocks); i++ {
nodeAddress := common.PosCandidateBlocks[i].NodeAddress
if stackRecordContainNodeAddress(stackRecord, nodeAddress) {
continue
}
coinNum := getCoinBlance(nodeAddress)
for j := 0; j < coinNum; j++ {
stackRecord = append(stackRecord, nodeAddress)
}
}
common.StackRecord = stackRecord
}
func PosGenerateBolck(oldBlack model.PosBlock, data string) {
stackNum := len(common.StackRecord)
index := rand.Intn(stackNum - 1)
winner := common.StackRecord[index]
var newBlock model.PosBlock
for i := 0; i < len(common.PosCandidateBlocks); i++ {
if winner == common.PosCandidateBlocks[i].NodeAddress {
newBlock.Timestamp = strconv.FormatInt(time.Now().Unix(), 10)
newBlock.Index = oldBlack.Index + 1
newBlock.Data = data
newBlock.PrevHash = oldBlack.Hash
newBlock.Hash = posCalculateHash(newBlock)
common.PosGlobleBlocks = append(common.PosGlobleBlocks, newBlock)
}
}
}
DPoS伪代码:server/dpos.go
package server
import (
"block_test/common"
"block_test/model"
"math/rand"
"sort"
"time"
)
func NeedRestVote() bool {
now := time.Now().Unix()
if (now - common.BeforeTime) > int64(common.DPosCycle) {
common.BeforeTime = now
return true
}
return false
}
func SortByVotes(witnessList []model.WitnessNode) {
sort.Slice(common.WitnessList, func(i, j int) bool {
return common.WitnessList[i].Votes > common.WitnessList[j].Votes
})
}
func SortWitnessList() {
if NeedRestVote() {
for i := 0; i < len(common.WitnessList); i++ {
common.WitnessList[i].Votes = rand.Intn(1000)
}
}
SortByVotes(common.WitnessList)
}
func isBadNode(node model.WitnessNode) bool {
return false
}
func CheckBadNode(node model.WitnessNode) {
for i := 0; i < len(common.WitnessList); i++ {
if isBadNode(common.WitnessList[i]) {
common.WitnessList = append(common.WitnessList[:i], common.WitnessList[i+1:]...)
}
}
}
func getNewNode() *model.WitnessNode {
var node model.WitnessNode
return &node
}
func isNewNodeComing() *model.WitnessNode {
node := getNewNode()
if node != nil {
return node
} else {
return nil
}
}
func getNode(pNode *model.WitnessNode) model.WitnessNode {
var node model.WitnessNode
node.NodeAddress = pNode.NodeAddress
node.Votes = pNode.Votes
node.Name = pNode.Name
return node
}
func CheckNewWitnessNode() {
for {
num := len(common.WitnessList)
if num < common.WitnessNum {
newWitness := isNewNodeComing()
if newWitness != nil {
node := getNode(newWitness)
common.WitnessList = append(common.WitnessList, node)
}
time.Sleep(100 * time.Millisecond)
}
}
}
func getWitnessByIndex(witnessNode []model.WitnessNode) *model.WitnessNode {
for i := 0; i < len(witnessNode); i++ {
if true {
return &witnessNode[i]
}
}
return nil
}
func generateBlock(node *model.WitnessNode) (model.DPosBlock, bool) {
var block model.DPosBlock
var timeOut bool
timeOut = false
return block, timeOut
}
func MakeBlock() model.DPosBlock {
SortWitnessList()
var resultBlock model.DPosBlock
for {
witness := getWitnessByIndex(common.WitnessList)
if witness == nil {
break
}
block, timeOut := generateBlock(witness)
resultBlock = block
if timeOut {
continue
}
break
}
return resultBlock
}
|