POS
每个旷工都有出块(即挖矿)的权力,只要出块成功,就有系统给出的奖励,这里不需要通过复杂的计算来挖矿,问题只在于谁来出块,股权越大,出块的概率就越大,反之,则相反。POS有很多变种,股权可以是持有币的数量,或者支付的数量等等。
但POS的问题是,大多数的持币人没有足够的专业知识或足够的预算,无法达到高性能节点所需的计算机硬件和软件要求,这时候就有了DPOS机制。
DPOS
在DPOS机制下,算法要求系统做三件事:
第一,随机指定生产者出场顺序;第二,不按顺序生产的区块无效;第三,每过一个周期洗牌一次,打乱原有顺序;
而且,DPOS允许所有矿池每三秒钟轮换一次,并且其他人已被安排在后续进程中,于是,没有人可以在预设位置外生产区块。如果一个块生产者这么做了,就可能被投票出局。
这意味着,生产者之间没有争夺,也不会遗漏区块,每三秒会有一个区块
1. 相对于POW和POS,DPOS机制最大的优点之一是共识达成的周期要短很多。
基于POW的比特币每秒处理7笔交易;基于POW和POS的以太坊每秒处理15笔交易;而基于DPOS的比特股(BTS)每秒能处理超10万的交易量。EOS将通过并行链的方式,预计最高可达到每秒数百万币的确认速度。
2. DPOS也会将一部分奖励分给网络维护节点和投票者,作为社区维护的奖励。
比如,LBTC就是采用DPOS机制出块,LBTC的持币者投票选出101个节点,这101个节点负责出块,并获得一定的奖励,而这其中每一个节点的投票者本身也会从中获得一定的回报。
简单的来说,你只需要去给你认为能被选中并承诺分红的节点投票,这些节点被选中后便可挖矿,你就可以获得节点承诺的相应分红。而此收益不需要你真实的操作挖矿,而仅仅只需要你动动小手指去投个票。有一些钱包已经支持LBTC的投票。
还有一些钱包更简单,不需要你手动投票,只需存入LBTC即可躺赚最优收益,Cobo此前上线的LBTC智能投票系统年化最高收益最高达300%,但是,随着投票数量增加,收益率也会相对减少,目前年化收益仍然在100%以上,想省心又想赚钱的朋友可以体验一下。
DPOS与POS最大的区别在于POS每一个节点都有权利挖矿,只要出块成功都有奖励,而DPOS要从普通节点中选取超级节点,超级节点进行共识。
超级节点指DPoS共识机制下的少数有权利生成区块的节点。
超级节点的五大职责:
1、提供服务器节点,保证节点的正常运行;
2、收集网络中的交易;
3、验证交易并把交易打包到区块;
4、广播区块给其他区块,在通过验证后将区块添加到自己本地区块链上;
5、保障并促进区块链项目的发展。
以下分享以下用go实现的简易POS与DPOS。
package main
import (
"crypto/rand"
"crypto/sha256"
"encoding/hex"
"fmt"
"log"
"math/big"
"strconv"
"time"
)
type block struct {
//上一个块的hash
prehash string
//本块hash
hash string
//时间戳
timestamp string
//区块内容
data string
//区块高度
height int
//挖出本块的地址
address string
}
//用于存储区块链
var blockchain []block
//代表挖矿节点
type node struct {
//代币数量
tokens int
//质押时间
days int
//节点地址
address string
}
//挖矿节点
var mineNodesPool []node
//概率节点池
var probabilityNodesPool []node
//初始化
func init() {
//手动添加两个节点
mineNodesPool = append(mineNodesPool, node{1000, 1, "AAAAAAAAAA"})
mineNodesPool = append(mineNodesPool, node{100, 3, "BBBBBBBBBB"})
//初始化随机节点池(挖矿概率与代币数量和币龄有关)
for _, v := range mineNodesPool {
for i := 0; i <= v.tokens*v.days; i++ {
probabilityNodesPool = append(probabilityNodesPool, v)
}
}
}
//生成新的区块
func generateNewBlock(oldBlock block, data string, address string) block {
newBlock := block{}
newBlock.prehash = oldBlock.hash
newBlock.data = data
newBlock.timestamp = time.Now().Format("2006-01-02 15:04:05")
newBlock.height = oldBlock.height + 1
newBlock.address = getMineNodeAddress()
newBlock.getHash()
return newBlock
}
//对自身进行散列
func (b *block) getHash() {
sumString := b.prehash + b.timestamp + b.data + b.address + strconv.Itoa(b.height)
hash := sha256.Sum256([]byte(sumString))
b.hash = hex.EncodeToString(hash[:])
}
//随机得出挖矿地址(挖矿概率跟代币数量与币龄有关)
func getMineNodeAddress() string {
bInt := big.NewInt(int64(len(probabilityNodesPool)))
//得出一个随机数,最大不超过随机节点池的大小
rInt, err := rand.Int(rand.Reader, bInt)
if err != nil {
log.Panic(err)
}
return probabilityNodesPool[int(rInt.Int64())].address
}
func main() {
//创建创世区块
genesisBlock := block{"0000000000000000000000000000000000000000000000000000000000000000", "", time.Now().Format("2006-01-02 15:04:05"), "我是创世区块", 1, "0000000000"}
genesisBlock.getHash()
//把创世区块添加进区块链
blockchain = append(blockchain, genesisBlock)
fmt.Println(blockchain[0])
i := 0
for {
time.Sleep(time.Second)
newBlock := generateNewBlock(blockchain[i], "我是区块内容", "00000")
blockchain = append(blockchain, newBlock)
fmt.Println(blockchain[i+1])
i++
}
}
package main
import (
"crypto/rand"
"crypto/sha256"
"encoding/hex"
"fmt"
"log"
"math/big"
"sort"
"strconv"
"time"
)
const (
voteNodeNum = 100
superNodeNum = 10
mineSuperNodeNum = 3
)
type block struct {
//上一个块的hash
prehash string
//本块hash
hash string
//时间戳
timestamp string
//区块内容
data string
//区块高度
height int
//挖出本块的节点地址
address string
}
//用于存储区块链
var blockchain []block
//普通节点
type node struct {
//代币数量
votes int
//节点地址
address string
}
//竞选节点
type superNode struct {
node
}
//投票节点池
var voteNodesPool []node
//竞选节点池
var starNodesPool []superNode
//存放可以挖矿的超级节点池
var superStarNodesPool []superNode
//生成新的区块
func generateNewBlock(oldBlock block, data string, address string) block {
newBlock := block{}
newBlock.prehash = oldBlock.hash
newBlock.data = data
newBlock.timestamp = time.Now().Format("2006-01-02 15:04:05")
newBlock.height = oldBlock.height + 1
newBlock.address = address
newBlock.getHash()
return newBlock
}
//对自身进行散列
func (b *block) getHash() {
sumString := b.prehash + b.timestamp + b.data + b.address + strconv.Itoa(b.height)
hash := sha256.Sum256([]byte(sumString))
b.hash = hex.EncodeToString(hash[:])
}
//投票
func voting() {
for _, v := range voteNodesPool {
rInt, err := rand.Int(rand.Reader, big.NewInt(superNodeNum+1))
if err != nil {
log.Panic(err)
}
starNodesPool[int(rInt.Int64())].votes += v.votes
}
}
//对挖矿节点进行排序
func sortMineNodes() {
sort.Slice(starNodesPool, func(i, j int) bool {
return starNodesPool[i].votes > starNodesPool[j].votes
})
superStarNodesPool = starNodesPool[:mineSuperNodeNum]
}
//初始化
func init() {
//初始化投票节点
for i := 0; i <= voteNodeNum; i++ {
rInt, err := rand.Int(rand.Reader, big.NewInt(10000))
if err != nil {
log.Panic(err)
}
voteNodesPool = append(voteNodesPool, node{int(rInt.Int64()), "投票节点" + strconv.Itoa(i)})
}
//初始化竞选节点
for i := 0; i <= superNodeNum; i++ {
starNodesPool = append(starNodesPool, superNode{node{0, "超级节点" + strconv.Itoa(i)}})
}
}
func main() {
fmt.Println("初始化", voteNodeNum, "个投票节点...")
fmt.Println(voteNodesPool)
fmt.Println("当前存在的", superNodeNum, "个竞选节点")
fmt.Println(starNodesPool)
fmt.Println("投票节点们开始进行投票...")
voting()
fmt.Println("结束投票,查看竞选节点们获得票数...")
fmt.Println(starNodesPool)
fmt.Println("对竞选节点按获得票数排序,前", mineSuperNodeNum, "名,当选超级节点")
sortMineNodes()
fmt.Println(superStarNodesPool)
fmt.Println("开始挖矿...")
genesisBlock := block{"0000000000000000000000000000000000000000000000000000000000000000", "", time.Now().Format("2006-01-02 15:04:05"), "我是创世区块", 1, "000000000"}
genesisBlock.getHash()
blockchain = append(blockchain, genesisBlock)
fmt.Println(blockchain[0])
i, j := 0, 0
for {
time.Sleep(time.Second)
newBlock := generateNewBlock(blockchain[i], "我是区块内容", superStarNodesPool[j].address)
blockchain = append(blockchain, newBlock)
fmt.Println(blockchain[i+1])
i++
j++
j = j % len(superStarNodesPool) //超级节点轮循获得出块权
}
}
结果图:
(1)POS(直接进行挖矿操作)
(2)DPOS(选出超级节点后进行挖矿操作,投票节点数为100)
参考:https://baijiahao.baidu.com/s?id=1603870079950594911&wfr=spider&for=pc
https://www.zhihu.com/question/286852548
https://blog.csdn.net/baidu_27836327/article/details/104219984