慕课网课程《私有区块链,我们一起GO》中"工作量证明及哈希算法"代码

/bitcoin_part2/src/coin/main.go

package main

import (
	"core"
	"fmt"
	"strconv"
)

func main()  {
	bc := core.NewBlockchain() //初始化区块链,创建第一个区块(创世纪区块)
	bc.AddBlock("Send 1 BTC to Ivan")
	bc.AddBlock("Send 2 more Btc to Ivan")

	for _, block := range bc.Blocks {
		fmt.Printf("Prev. hash: %x\n", block.PrevBlockHash)
		fmt.Printf("Data: %s\n", block.Data)
		fmt.Printf("Hash: %x\n", block.Hash)

		pow := core.NewProofofWork(block)
		fmt.Printf("PoW: %s\n", strconv.FormatBool(pow.Validate()))    //工作量证明
		fmt.Println()
	}
}

/bitcoin_part2/src/core/block.go

package core

import (
	"bytes"
	"crypto/sha256"
	"strconv"
	"time"
)

//Block keeps block headers
type Block struct {
	Timestamp int64 //区块创建时间戳
	Data []byte   //区块包含的数据
	PrevBlockHash []byte //前一个区块的哈希值
	Hash []byte //区块自身的哈希值,用于校验区块数据有效
	Nonce int
}

//NewBlock creates and return Blocks
func NewBlock(data string, prevBlockHash []byte) *Block {
	block := &Block{time.Now().Unix(), []byte(data), prevBlockHash, []byte{}, int(0)}  //Nonce为0是我自己加的
	pow := NewProofofWork(block)
	nonce, hash := pow.Run()

	block.Hash = hash[:]
	block.Nonce = nonce
	return block
}

//SetHash calculates and sets block hash
func (b *Block) SetHash()  {
	timestamp := []byte(strconv.FormatInt(b.Timestamp, 10))     //时间戳转字节数组
	headers := bytes.Join([][]byte{b.PrevBlockHash, b.Data, timestamp}, []byte{})
	hash := sha256.Sum256(headers)
	b.Hash = hash[:]
}

//NewGenesizeBlock creates and returns genesis Block
func NewGenesisBlock() *Block {
	return NewBlock("Genesis Block", []byte{})
}

/bitcoin_part2/src/core/blockchain.go

package core

//Blockchain keeps a sequence of Blocks
type Blockchain struct {
	Blocks []*Block
}

//AddBlock saves provided data as a block in the blockchain
func (bc *Blockchain) AddBlock(data string)  {
	prevBlock := bc.Blocks[len(bc.Blocks)-1] //取出当前区块链中最新的区块
	newBlock := NewBlock(data, prevBlock.Hash)
	bc.Blocks = append(bc.Blocks, newBlock)
}

//NewBlockchain creates a new Blockchain with genesis Block
func NewBlockchain() *Blockchain {
	return &Blockchain{[]*Block{NewGenesisBlock()}}
}

/bitcoin_part2/src/core/proofofwork.go

package core

import (
	"bytes"
	"crypto/sha256"
	"fmt"
	"math"
	"math/big"
)

var(
	maxNonce = math.MaxInt64   //整数64位里面最大的数值
)

const targetBits  = 20   //目标位

// proofofwork represents a proof-of-work
type ProofofWork struct {
	block *Block
	target *big.Int  //目标(对block区块进行计算,满足这个设定的目标)
}

// NewProofofwork builds and returns a ProofofWork
func NewProofofWork(b *Block) *ProofofWork {
	target := big.NewInt(1)   //整数1
	target.Lsh(target, uint(256 - targetBits)) //对整数前面的bit进行移位操作,前20位变为0
	pow := &ProofofWork{b,target}
	return pow
}

func (pow *ProofofWork) prepareData(nonce int) []byte {
	data := bytes.Join(
		[][]byte{
			pow.block.PrevBlockHash,
			pow.block.Data,
			IntToHex(pow.block.Timestamp),
			IntToHex(int64(targetBits)),
			IntToHex(int64(nonce)),
		},
		[]byte{},
		)
	return data
}

func (pow *ProofofWork) Run() (int, []byte) {
	var hashInt big.Int
	var hash [32]byte
	nonce := 0

	fmt.Printf("Mining the block containing \"%s\"\n", pow.block.Data)
	for nonce < maxNonce {
		data := pow.prepareData(nonce)

		hash = sha256.Sum256(data)
		fmt.Printf("\r%x", hash)
		hashInt.SetBytes(hash[:])   //把哈希值转换成一个整数

		if hashInt.Cmp(pow.target) == -1{
			break
		} else {
			nonce++
		}
	}
	fmt.Print("\n\n")

	return nonce, hash[:]
}

// Validate validates blocks Pow
func (pow *ProofofWork) Validate() bool {
	var hashInt big.Int

	data := pow.prepareData(pow.block.Nonce)
	hash := sha256.Sum256(data)
	hashInt.SetBytes(hash[:])

	isValid := hashInt.Cmp(pow.target) == -1
	return isValid
}

/bitcoin_part2/src/core/utils.go

package core

import (
	"bytes"
	"crypto/sha256"
	"encoding/binary"
	"log"
)

// IntToHex converts an int64 to a byte array
func IntToHex(num int64) []byte {
	buff := new(bytes.Buffer)
	err := binary.Write(buff, binary.BigEndian, num)
	if err != nil{
		log.Panic(err)
	}

	return buff.Bytes()
}

func DataToHash(data []byte) []byte {
	hash := sha256.Sum256(data)
	return hash[:]
}

代码来自:https://www.imooc.com/video/17556

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值