共识算法4--股权权益证明算法改进

共识算法4--股权权益证明算法改进

 

共识算法2--股权权益证明简介及算法实现 对PoS算法进行了简介,并初步实现了一个简单版本的PoS算法,本文根据共识算法2对PoS算法进一步完善,实现从电脑终端加入用户,然后根据用户持币时间采用PoS确定挖矿用户。

 

1、股权权益证明改进说明

博文共识算法2中采用初始化用户的方式来生成挖矿用户,并根据其币龄采用PoS算法挖矿,但是实际中不可能采用初始化用户的方法生成用户,多为动态添加用户。因此,此处对其进行改进,通过系统终端添加挖矿用户,并根据其币龄采用PoS挖矿。

 

2、PoS算法改进实现 

本文改进的PoS算法具体实施如下:

PoS服务启动,等待终端用户加入(若无用户则采用默认的noMiner来挖矿),用户加入后将其放进对应的节点数组中, 系统每10s中通过PoS选择一个矿工挖矿,并将挖到的矿放到区块数组中。

本案例不足之处:暂未对用户添加奖励,挖矿后年未同步更新各个用户的币龄,未对终端用户做区分,后续将逐渐完善这些不足之处。

PoS算法单机版本源码:

// c6_PoS
package main

//该版本PoS实现在终端中加入挖矿用户,挖矿时候根据挖矿用户的持币时间和随机函数来确定哪个用户挖矿
import (
	"bufio"
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"io"
	"math/rand"
	"net"
	"os"
	"strconv"
	"time"
)

//创建区块
type Block struct {
	Index     int //区块高度
	Data      int //交易记录、数据
	Prehash   string
	Hash      string
	Timestamp string
	Validator string //终端地址
}

//计算string 的 hash值
func calculateHash(record string) string {
	h := sha256.New()
	h.Write([]byte(record))
	hashed := h.Sum(nil)
	return hex.EncodeToString(hashed)
}

//计算Block 的 hash值
func calculateBlockHash(block Block) string {
	record := block.Timestamp + strconv.Itoa(block.Data) + block.Prehash + strconv.Itoa(block.Index)
	hashCode := calculateHash(record)
	return hashCode
}

//生成区块切片,用于存放区块链
var Blockchain []Block

//生成一个新的区块
func generateNextBlock(oldBlock Block, data int, vald string) Block {
	var newBlock Block
	//设置区块高度
	newBlock.Index = oldBlock.Index + 1
	newBlock.Timestamp = time.Now().String()
	newBlock.Prehash = oldBlock.Hash
	newBlock.Data = data
	newBlock.Hash = calculateBlockHash(newBlock)
	newBlock.Validator = vald
	//添加到区块链
	Blockchain = append(Blockchain, newBlock)
	return newBlock
}

//创建创世区块
func genesisBlock() Block {
	var genesisBlock = Block{0, 0, "00prehash", "00hash", time.Now().String(), "00"}
	//计算创世块的hash
	genesisBlock.Hash = calculateBlockHash(genesisBlock)
	Blockchain = append(Blockchain, genesisBlock)
	return genesisBlock
}

//创建conn终端连接的数组,用于保存终端用户
var connAddr []net.Conn

//创建节点类型
type Node struct {
	//终端地址
	Addres string
	//持币时间
	CoinsTime int
}

//保存已经连接的终端的对象
var nodes []Node

//通过pos共识算法选择矿工
func chooseWinner() string {
	var Pool []string
	//根据持币时间把对应的矿工地址存放到数组中
	for i := 0; i < len(nodes); i++ {
		node := nodes[i]
		Pool = append(Pool, node.Addres)
	}
	if len(Pool) != 0 {
		//通过随机值找到挖矿的矿工
		rand.Seed(time.Now().Unix())
		r := rand.Intn(len(Pool))
		workerAddr := Pool[r]
		return workerAddr //返回矿工地址
	}
	return "noMiner" //无矿工的时候默认为noMiner
}

//使用通道实现线程间通信
var communication = make(chan string)

func main() {
	fmt.Println("Hello PoS!")
	/* test
	genesisBlock := genesisBlock()
	newBlock := generateNextBlock(genesisBlock, 1)
	generateNextBlock(newBlock, 2)
	for i := range Blockchain {
		fmt.Println(Blockchain[i])
	}
	*/
	genesisBlock := genesisBlock()
	currentBlock := genesisBlock
	fmt.Println("genesisBlock:", genesisBlock)
	//通过终端连接到PoS服务
	//创建监听
	netListen, err := net.Listen("tcp", "192.168.120.54:1234") //此处ip为本机器ip,端口为1234
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	defer netListen.Close()

	go func() {
		//通过矿工实现区块挖矿
		rand.Seed(time.Now().Unix())
		for {
			w := <-communication
			//fmt.Println(w)
			//将新的区块利用w矿工添加到数组中
			currentBlock = generateNextBlock(currentBlock, rand.Intn(1000), w) //区块数据此处随机为0-1000,实际为默尔克树的hash
			fmt.Println("newBlock:", currentBlock)
		}
	}()

	go func() {
		//每隔10s选择一次矿工
		for {
			time.Sleep(10 * time.Second)
			winner := chooseWinner()
			fmt.Println("PoS choose winner:", winner)
			//将矿工放入到通道中
			communication <- winner
		}
	}()

	//等待连接
	for {
		conn, _ := netListen.Accept()
		connAddr = append(connAddr, conn)
		//扫描终端
		scanbalance := bufio.NewScanner(conn)
		io.WriteString(conn, "please input holding period:\n") //终端中输入持币周期

		//扫描终端里写了什么
		go func() {
			//在子线程中扫描终端中的内容
			for scanbalance.Scan() {
				txt := scanbalance.Text()
				fmt.Println("\nTerminal holding period:", txt)
				//通过时间戳创建地址
				addr := calculateHash(time.Now().String()) //此处暂时把时间的hash作为终端用户的hash
				coins, _ := strconv.Atoi(txt)
				node := Node{addr, coins}
				//将连接的终端放在数组中
				nodes = append(nodes, node)
				fmt.Println("usr number:", len(nodes))
				for i := 0; i < len(nodes); i++ {
					fmt.Println("addr:", nodes[i].Addres, "CoinsTime:", nodes[i].CoinsTime)
				}
			}
		}()
	}
}

//此时可以通过telnet ip 1234连接到PoS服务器,终端输入信息回车后,即可发送到svr
//telnet 192.168.120.54 1234

通过telnet ip port分别先后添加币龄为11和21的用户,运行结果:

E:/Software/Golang/go1.11/bin/go.exe run c6_PoS.go [E:/Code/Golang/gongshi]
Hello PoS!
genesisBlock: {0 0 00prehash fffed895b697b36811ebb8f485ba6fba4d5a40cad51788ebc8f3315b0a7185d8 2019-01-23 14:57:24.7674002 +0800 CST m=+0.002000001 00}
PoS choose winner: noMiner
newBlock: {1 524 fffed895b697b36811ebb8f485ba6fba4d5a40cad51788ebc8f3315b0a7185d8 d36bb430282351a1596952140d14432e89d0faa75b592eef7ab2d6f7bb49ea36 2019-01-23 14:57:34.7754002 +0800 CST m=+10.010000001 noMiner}

Terminal holding period: 11
usr number: 1
addr: 719ac8ceb8f6139972ada537da6a19156ad9a3eafdcc068368018be443a6cfc3 CoinsTime: 11
PoS choose winner: 719ac8ceb8f6139972ada537da6a19156ad9a3eafdcc068368018be443a6cfc3
newBlock: {2 460 d36bb430282351a1596952140d14432e89d0faa75b592eef7ab2d6f7bb49ea36 e7cf8e22fde1f6ab71bf1c848902d5f1f3df63753e0740854e292a1bf7c6dc42 2019-01-23 14:57:44.7754002 +0800 CST m=+20.010000001 719ac8ceb8f6139972ada537da6a19156ad9a3eafdcc068368018be443a6cfc3}
PoS choose winner: 719ac8ceb8f6139972ada537da6a19156ad9a3eafdcc068368018be443a6cfc3
newBlock: {3 540 e7cf8e22fde1f6ab71bf1c848902d5f1f3df63753e0740854e292a1bf7c6dc42 59ca95145cc84bfe206e8765241c4a02a81cf1a7d1fb0f460a7b489542bb35a5 2019-01-23 14:57:54.7754002 +0800 CST m=+30.010000001 719ac8ceb8f6139972ada537da6a19156ad9a3eafdcc068368018be443a6cfc3}

Terminal holding period: 21
usr number: 2
addr: 719ac8ceb8f6139972ada537da6a19156ad9a3eafdcc068368018be443a6cfc3 CoinsTime: 11
addr: b0c6cb4989a1ec71c9014fdff0f50ee0d89462b19b498ce04de616e2d515a969 CoinsTime: 21
PoS choose winner: b0c6cb4989a1ec71c9014fdff0f50ee0d89462b19b498ce04de616e2d515a969
newBlock: {4 389 59ca95145cc84bfe206e8765241c4a02a81cf1a7d1fb0f460a7b489542bb35a5 26d0abb4e4a5e4b9be9406ac1b5b8be38f8a325c9e35b6fbc3624a429c04689f 2019-01-23 14:58:04.7754002 +0800 CST m=+40.010000001 b0c6cb4989a1ec71c9014fdff0f50ee0d89462b19b498ce04de616e2d515a969}
PoS choose winner: 719ac8ceb8f6139972ada537da6a19156ad9a3eafdcc068368018be443a6cfc3
newBlock: {5 604 26d0abb4e4a5e4b9be9406ac1b5b8be38f8a325c9e35b6fbc3624a429c04689f e61436f01c6176e5646196e4a01902b65dae9685cc36c5341145d0ea4c12cda3 2019-01-23 14:58:14.7754002 +0800 CST m=+50.010000001 719ac8ceb8f6139972ada537da6a19156ad9a3eafdcc068368018be443a6cfc3}
PoS choose winner: b0c6cb4989a1ec71c9014fdff0f50ee0d89462b19b498ce04de616e2d515a969
newBlock: {6 821 e61436f01c6176e5646196e4a01902b65dae9685cc36c5341145d0ea4c12cda3 f4506431b849a0a7774632b9c0ecc055b5582a06c7b9afa82d757a4f119e2462 2019-01-23 14:58:24.7754002 +0800 CST m=+60.010000001 b0c6cb4989a1ec71c9014fdff0f50ee0d89462b19b498ce04de616e2d515a969}
PoS choose winner: b0c6cb4989a1ec71c9014fdff0f50ee0d89462b19b498ce04de616e2d515a969
newBlock: {7 756 f4506431b849a0a7774632b9c0ecc055b5582a06c7b9afa82d757a4f119e2462 ed710738d44a811bf06daaa4d2b2ddbef6322909d1960a5a38222ad9a60f3dc1 2019-01-23 14:58:34.7754002 +0800 CST m=+70.010000001 b0c6cb4989a1ec71c9014fdff0f50ee0d89462b19b498ce04de616e2d515a969}
exit status 1
错误: 进程退出代码 1.

结果表明,未添加终端用户的时候默认使用noMiner进行挖矿,添加币龄为11的用户后,其挖矿为币龄11的用户了,继续添加币龄为21的用户,其挖矿根据PoS随机为11和21两用户之一。

 

3、说明

本代码当前测试环境为golang1.11。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

昕光xg

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值