Blockchain practice (II) realization of pow workload proof | 15th day of settlement

Xiaosheng Fanyi 2021-08-07 17:16:45 阅读数:840

本文一共[544]字,预计阅读时长:1分钟~
blockchain practice ii realization pow

Version 2

  1. Define the structure of a proof of effort ProofOfWork

    block

​ The target

  1. Provide a creative PoW Methods

    NewProofOfWork( Parameters )

  2. Provide a method to calculate the hash value

    Run()

  3. Provide a check function

    IsValid()

Structure catalog  Insert picture description here

block.go

package main
import (
"time"
)
/* 1. Define the structure of a block Block a. Block head :6 A field b. Block body : String representation data */
// block 
type Block struct {
Version int64 // edition 
PerBlockHash []byte // Of the previous block hash value 
Hash []byte // Of the current block hash value , To simplify the code 
MerKelRoot []byte // Merkelgen 
TimeStamp int64 // Time flies 
Bits int64 // Difficulty value 
Nonce int64 // Random value 
// Block body 
Data []byte // Transaction information 
}
/* Provides a way to create blocks NewBlock( Parameters ) */
func NewBlock(data string ,prevBlockHash []byte) *Block {
var block Block
block = Block{
Version: 2,
PerBlockHash: prevBlockHash,
//Hash: []byte{}, // Blocks do not store hash value , After the node accepts the block, it is calculated independently and stored locally .
MerKelRoot: []byte{},
TimeStamp: time.Now().Unix(),
Bits: targetBits,
Nonce: 0,
Data: []byte(data),
}
// block.SetHash() // fill Hash
PoW:= NewProofOfWork(&block)
nonce , hash :=PoW.Run()
block.Nonce=nonce
block.Hash=hash
return &block
}
/* func (block *Block) SetHash() { // The source code is to pass two-dimensional slices func Join(s [][]byte, sep []byte) []byte tmp :=[][]byte{ IntToByte(block.Version), block.PerBlockHash, block.MerKelRoot, IntToByte(block.TimeStamp), IntToByte(block.Bits), IntToByte(block.Nonce), } data:=bytes.Join(tmp,[]byte{}) // Then calculate hash hash := sha256.Sum256(data) block.Hash = hash[:] // Variable slice } */
// Founding block 
func NewGensisBlock() *Block{
return NewBlock("Genesis Block!",[]byte{})
}
 Copy code 

blockChain.go

package main
/* 1. Define a blockchain structure BlockChain Block Array */
type BlockChain struct {
blocks []*Block
}
/* 2. Provide a create BlockChain() Methods NewBlockChain() */
func NewBlockChain() *BlockChain {
block := NewGensisBlock()
return &BlockChain{blocks:[]*Block{block}} // Create a blockchain with only one element , initialization 
}
/* 3. Provide a way to add blocks AddBlock( Parameters ) */
func (bc *BlockChain)AddBlock(data string) {
PerBlockHash := bc.blocks[len(bc.blocks)-1].Hash // The hash of this block is the hash value of the previous block 
block := NewBlock(data,PerBlockHash)
bc.blocks = append(bc.blocks,block)
}
 Copy code 

proofOfWork.go

package main
import (
"bytes"
"crypto/sha256"
"fmt"
"math"
"math/big"
)
/* 1. Define the structure of a proof of effort ProofOfWork block The target */
type ProofOfWork struct {
block *Block
target *big.Int // The target 
}
/* 2. Provide a creative PoW Methods NewProofOfWork( Parameters ) */
const targetBits = 24
func NewProofOfWork(block *Block) *ProofOfWork { // Proof of workload 
target := big.NewInt(1) //000....001
target.Lsh(target,uint(256-targetBits)) // take 1 Move to the left //ox00000010000000..00
pow:=ProofOfWork{
block: block,
target: target,
}
return &pow
}
func (pow *ProofOfWork) PrepareData(nonce int64) []byte {
// The source code is to pass two-dimensional slices func Join(s [][]byte, sep []byte) []byte
block := pow.block
tmp :=[][]byte{
IntToByte(block.Version),
block.PerBlockHash,
block.MerKelRoot,
IntToByte(block.TimeStamp),
IntToByte(block.Bits),
IntToByte(block.Nonce),
}
data:=bytes.Join(tmp,[]byte{}) // Then calculate hash
return data
}
/* 2. Provide a method to calculate the hash value Run() */
func (pow *ProofOfWork)Run() (int64,[]byte) {
/* Pseudo code for nonce { hash := sha256(block_data+nonce) if (hash) < pow.target{ flag=1 }else{ flag=0 } } return nonce,hash[:] */
//1. With data 
//2. The hash value is converted to big.Int type 
var hash [32]byte
var nonce int64 = 0
var hashInt big.Int
fmt.Println(" Start mining !")
fmt.Printf(" difficulty target hash : %x\n" ,pow.target.Bytes())
for nonce < math.MaxInt64 {
data:=pow.PrepareData(nonce)
hash = sha256.Sum256(data)
// Cmp compares x and y and returns:
//
// -1 if x < y
// 0 if x == y
// +1 if x > y
//
hashInt.SetBytes(hash[:])
if hashInt.Cmp(pow.target) == -1 {
fmt.Printf("Found ,nonce :%d ,hash :%x \n",nonce,hash)
}else {
//fmt.Printf("Not Found ,current nonce :%d ,hash :%x \n",nonce,hash)
nonce++
}
}
return nonce,hash[:]
}
/* 3. Provide a check function IsValid() */
func (pow *ProofOfWork)IsValid() bool{
var hashInt big.Int
data := pow.PrepareData(pow.block.Nonce)
hash:=sha256.Sum256(data)
hashInt.SetBytes(hash[:])
return hashInt.Cmp(pow.target) == -1 // If it is -1 Just find it, just 
}
 Copy code 

utils.go

package main
import (
"bytes"
"encoding/binary"
"fmt"
"os"
)
func IntToByte(num int64) []byte {
//func Write(w io.Writer, order ByteOrder, data interface{}) error {
var buffer bytes.Buffer
err := binary.Write(&buffer, binary.BigEndian, num)
CheckErr("IntToByte",err)
return buffer.Bytes()
}
func CheckErr(position string,err error) {
if err != nil {
fmt.Println("error ,pos:",position,err)
os.Exit(1)
}
}
 Copy code 

main.go

package main
import "fmt"
func main() {
bc := NewBlockChain()
bc.AddBlock("A send B 1BTC")
bc.AddBlock("B send C 1BTC")
for _,block := range bc.blocks {
fmt.Printf("Version : %d\n",block.Version)
fmt.Printf("PerBlockHash : %x\n",block.PerBlockHash)
fmt.Printf("Hash : %x\n",block.Hash)
fmt.Printf("MerKelRoot : %x\n",block.MerKelRoot)
fmt.Printf("TimeStamp : %d\n",block.TimeStamp)
fmt.Printf("Bits : %d\n",block.Bits)
fmt.Printf("Nonce : %d\n",block.Nonce)
fmt.Printf("Data : %s\n",block.Data)
fmt.Printf("IsVaild : %v\n",NewProofOfWork(block).IsValid())
}
}
 Copy code 

result

 Insert picture description here

structure

 Insert picture description here

版权声明:本文为[Xiaosheng Fanyi]所创,转载请带上原文链接,感谢。 https://netfreeman.com/2021/08/20210807171055860d.html