权益证明,它提出来币龄的概念,币龄 = 持有的货币数 * 持有时间,比如说我有100币,持有了30天,那么我的币龄就是3000。币龄越大的节点呢获取记账权(也就是生成区块)的概率越大。每次记完账之后,该节点的币龄就清空。当然,刚获取的币不能直接参与币龄计算,一般是30天之后开始计算币龄。
那么这样会产生一个问题:囤币来获取绝对记账权。为了防止这种情况发生,会设置一个最大概率,一般设置90天时获得最大记账概率,之后不再增加。
但是POS本质上还是类似POW的暴力计算,只不过币多的人更有可能挖到矿,降低了POW的全网一致难度,谁算力强谁记账的局限性。
实验步骤:
本实验将通过go语言实现最简单的POS共识机制算法
- 实验准备
新建文件pos.go,并使用vs code编辑器打开。
导入所需包:
package main
import (
"bytes"
"crypto/sha256"
"encoding/binary"
"fmt"
"math"
"math/big"
"math/rand"
"time"
)
定义常量设置最大最小概率,这里由于不可能等30天之后再计算币龄,我设置10秒之后开始计算,并且防止数据过大,按分钟计时:
const (
dif = 2
INT64_MAX = math.MaxInt64
MaxProbably = 255
MinProbably = 235
MaxCoinAge = 10
Minute = 60
)
定义币的数据结构和一个币池,这里币中提出了地址Address概念,一般理解为钱包地址,一般一个钱包属于一个用户,表明这个币的所有权是这个地址对应的用户:
type Coin struct {
Time int64
Num int
Address string
}
var CoinPool []Coin
定义区块和链:
type Block struct {
PrevHash []byte
Hash []byte
Data string
Height int64
Timestamp int64
Coin Coin
Nonce int
Dif int64
}
type BlockChain struct {
Blocks []Block
}
init函数,设置随机数种子和币池初始化,会在main函数开始前自动执行:
func init() {
rand.Seed(time.Now().UnixNano())
CoinPool = make([]Coin, 0)
}
生成创世块,传入的参数是区块上的数据data和挖矿地址addr,这里每个区块的币随机给出1到5,币池增加创世块的币:
func GenesisBlock(data string, addr string) *BlockChain {
var bc BlockChain
bc.Blocks = make([]Block, 1)
newCoin := Coin{
Time: time.Now().Unix(),
Num: 1 + rand.Intn(5),
Address: addr,
}
bc.Blocks[0] = Block{
PrevHash: []