随着区块链给世界市场带来的革命,在作出预测之前了解基础知识至关重要。在本文中,我们将探讨权益证明的基础知识,该证明是一种区块链协议,类似于一种在区块链中伪造新区块的彩票方法。
了解权益证明
Go中的权益证明
导入“区块链”
package main
import (
"crypto/sha256"
"encoding/hex"
"errors"
"fmt"
"log"
math "math/rand"
"time"
)
type PoSNetwork struct {
Blockchain []*Block
BlockchainHead *Block
Validators []*Node
}
type Node struct {
Stake int
Address string
}
type Block struct {
Timestamp string
PrevHash string
Hash string
ValidatorAddr string
}
逐块建造区块链砖
func (n PoSNetwork) GenerateNewBlock(Validator *Node) ([]*Block, *Block, error) {
if err := n.ValidateBlockchain(); err != nil {
Validator.Stake -= 10
return n.Blockchain, n.BlockchainHead, err
}
currentTime := time.Now().String()
newBlock := &Block {
Timestamp: currentTime,
PrevHash: n.BlockchainHead.Hash,
Hash: NewBlockHash(n.BlockchainHead),
ValidatorAddr: Validator.Address,
}
if err := n.ValidateBlockCandidate(newBlock); err != nil {
Validator.Stake -= 10
return n.Blockchain, n.BlockchainHead, err
} else {
n.Blockchain = append(n.Blockchain, newBlock)
}
return n.Blockchain, newBlock, nil
}
func NewBlockHash(block *Block) string {
blockInfo := block.Timestamp + block.PrevHash + block.Hash + block.ValidatorAddr
return newHash(blockInfo)
}
func newHash(s string) string {
h := sha256.New()
h.Write([]byte(s))
hashed := h.Sum(nil)
return hex.EncodeToString(hashed)
}
验证我们的区块链
func (n PoSNetwork) ValidateBlockchain() error {
if len(n.Blockchain) <= 1 {
return nil
}
currBlockIdx := len(n.Blockchain)-1
prevBlockIdx := len(n.Blockchain)-2
for prevBlockIdx >= 0 {
currBlock := n.Blockchain[currBlockIdx]
prevBlock := n.Blockchain[prevBlockIdx]
if currBlock.PrevHash != prevBlock.Hash {
return errors.New("blockchain has inconsistent hashes")
}
if currBlock.Timestamp <= prevBlock.Timestamp {
return errors.New("blockchain has inconsistent timestamps")
}
if NewBlockHash(prevBlock) != currBlock.Hash {
return errors.New("blockchain has inconsistent hash generation")
}
currBlockIdx--
prevBlockIdx--
}
return nil
}
func (n PoSNetwork) ValidateBlockCandidate(newBlock *Block) error {
if n.BlockchainHead.Hash != newBlock.PrevHash {
return errors.New("blockchain HEAD hash is not equal to new block previous hash")
}
if n.BlockchainHead.Timestamp >= newBlock.Timestamp {
return errors.New("blockchain HEAD timestamp is greater than or equal to new block timestamp")
}
if NewBlockHash(n.BlockchainHead) != newBlock.Hash {
return errors.New("new block hash of blockchain HEAD does not equal new block hash")
}
return nil
}
那么,我们如何决定何时添加新块?
func (n PoSNetwork) NewNode(stake int) []*Node {
newNode := &Node{
Stake: stake,
Address: randAddress(),
}
n.Validators = append(n.Validators, newNode)
return n.Validators
}
func randAddress() string {
b := make([]byte, 16)
_, _ = math.Read(b)
return fmt.Sprintf("%x", b)
}
func (n PoSNetwork) SelectWinner() (*Node, error) {
var winnerPool []*Node
totalStake := 0
for _, node := range n.Validators {
if node.Stake > 0 {
winnerPool = append(winnerPool, node)
totalStake += node.Stake
}
}
if winnerPool == nil {
return nil, errors.New("there are no nodes with stake in the network")
}
winnerNumber := math.Intn(totalStake)
tmp := 0
for _, node := range n.Validators {
tmp += node.Stake
if winnerNumber < tmp {
return node, nil
}
}
return nil, errors.New("a winner should have been picked but wasn't")
}
汇集全部
我们现在所需要的就是将我们的函数和数据类型绑定在一起。我们在main()函数中做好所有的事情,第一步是设置一个随机种子与当前时间作为我们的输入。不要使用时间作为随机种子的输入,因为它实际上会在解码哈希输出时引入安全漏洞。
在这个示例中,我们需要实例化一个新的ProofStake网络,其中有一个被称为Genesis块,也就是我们所知的块。区块链中的第一个区块。一旦我们这样做,我们也设置网络的BlockchainHead等于第一个块。
func main() {
// set random seed
math.Seed(time.Now().UnixNano())
// generate an initial PoS network including a blockchain with a genesis block.
genesisTime := time.Now().String()
pos := &PoSNetwork{
Blockchain: []*Block{
{
Timestamp: genesisTime,
PrevHash: "",
Hash: newHash(genesisTime),
ValidatorAddr: "",
},
},
}
pos.BlockchainHead = pos.Blockchain[0]
// instantiate nodes to act as validators in our network
pos.Validators = pos.NewNode(60)
pos.Validators = pos.NewNode(40)
// build 5 additions to the blockchain
for i := 0; i < 5; i++ {
winner, err := pos.SelectWinner()
if err != nil {
log.Fatal(err)
}
winner.Stake += 10
pos.Blockchain, pos.BlockchainHead, err = pos.GenerateNewBlock(winner)
if err != nil {
log.Fatal(err)
}
fmt.Println("Round ", i)
fmt.Println("\tAddress:", pos.Validators[0].Address, "-Stake:", pos.Validators[0].Stake)
fmt.Println("\tAddress:", pos.Validators[1].Address, "-Stake:", pos.Validators[1].Stake)
}
pos.PrintBlockchainInfo()
}
然后,我们添加两个节点的网络作为验证器与60和40令牌作为他们的初始股份。在五次迭代中,我们将为区块链选择一个新的赢家,如果有任何错误,我们的程序将崩溃-因为做原型我们通过新选择的赢家产生一个新的块,并打印出每一轮的每个节点的总桩。
最后,我们将打印出我们新制作的区块链:
$ go run main.go
Round 0
Address: f8d44bb083078de97b8428f4f9548130 -Stake: 70
Address: de6ae18584f02b3388569191a04a4b4a -Stake: 40
Round 1
Address: f8d44bb083078de97b8428f4f9548130 -Stake: 70
Address: de6ae18584f02b3388569191a04a4b4a -Stake: 50
Round 2
Address: f8d44bb083078de97b8428f4f9548130 -Stake: 80
Address: de6ae18584f02b3388569191a04a4b4a -Stake: 50
Round 3
Address: f8d44bb083078de97b8428f4f9548130 -Stake: 90
Address: de6ae18584f02b3388569191a04a4b4a -Stake: 50
Round 4
Address: f8d44bb083078de97b8428f4f9548130 -Stake: 100
Address: de6ae18584f02b3388569191a04a4b4a -Stake: 50
Block 0 Info:
Timestamp: 2021-04-12 MDT m=+0.000120025
Previous Hash:
Hash: c5d04de14efed52ce84889c6382f9d307d5b98093d93a84b419478
Validator Address:
Block 1 Info:
Timestamp: 2021-04-12 MDT m=+0.000277288
Previous Hash: c5d04de14efed52ce84889c6382f9d307d5b98093d93a
Hash: d58e90a75b71ac62ef938fc0148314a7f864ad50bd702f959e2d27
Validator Address: f8d44bb083078de97b8428f4f9548130
Block 2 Info:
Timestamp: 2021-04-12 MDT m=+0.000306562
Previous Hash: d58e90a75b71ac62ef938fc0148314a7f864ad50bd702
Hash: e6bfdd6c2c869607e2d9a81b84ddf4478756fedff78a03746cde11
Validator Address: de6ae18584f02b3388569191a04a4b4a
Block 3 Info:
Timestamp: 2021-04-12 MDT m=+0.000321755
Previous Hash: e6bfdd6c2c869607e2d9a81b84ddf4478756fedff78a0
Hash: 8e3dbacc4a610b1665658bc9e7238963eda0d5bbbf3ce809e8fa6e
Validator Address: f8d44bb083078de97b8428f4f9548130
Block 4 Info:
Timestamp: 2021-04-12 MDT m=+0.000333024
Previous Hash: 8e3dbacc4a610b1665658bc9e7238963eda0d5bbbf3ce
Hash: 22760f8deb96c354a4050a3c48741be062bccfa9c51571c170065a
Validator Address: f8d44bb083078de97b8428f4f9548130
Block 5 Info:
Timestamp: 2021-04-12 MDT m=+0.000347521
Previous Hash: 22760f8deb96c354a4050a3c48741be062bccfa9c5157
Hash: d2a5047f7d8a7696c1d0fb9ec49b56d2e71bbcedaaebc83a18b7a5
Validator Address: f8d44bb083078de97b8428f4f9548130
作者:链三丰,来源:区块链研究实验室
郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。
郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。