简单区块链的实现(带POW挖矿系统)
蓝天天使2017
发表于 2022-12-7 11:38:58
249
0
0
代码分析* c2 t' d3 D) `+ w3 j
三大模块
代码还是比较简单清晰的,主要有三个模块,Block模块、BlockChain模块、POW模块即挖矿模块。
运行流程
首先从定义一个区块开始,一个区块中包含的信息有区块信息,时间戳,前区块哈希值,现区块哈希值,经过挖矿后得到的哈希碰撞值等等。
接着我们开启一个切片用来存放一个个区块,但是第一个区块是比较特殊的,我们称之为创世区块,在真实的比特币中,第一个区块是由创始人中本聪挖矿所得,没有前哈希值,所以这里我们直接将第一个创世区块创建添加到区块切片中。
然后给到一个添加区块的方法,用户添加区块信息后,经过POW挖矿系统才能成功添加到区块链上。
有了大概的运行流程接下来再来看代码就会轻松很多了。8 R0 l# n h1 V, U2 K& a! {; ]+ G" x
package main
import (
"math/big"
"bytes"
"encoding/binary"
"crypto/sha256"1 S Z2 H5 ]/ j2 S
"fmt"# ~ Q9 ~7 z3 D1 n& M1 P! r- g
"time"
)
//Block模块
type Block struct {: v& T. [% [7 q2 n D" P) t
Version uint64 //版本号; P- N/ M4 k$ \& v9 @& x3 C
MerkelRoot []byte //这是一个默克尔数,这里先默认为空) l* h* z5 Q' q8 g& Y
TimeStamp string //时间戳, K4 h ~6 v- i, T8 R! E
Difficulty uint64 //难度值
Nonce uint64 //挖矿所找到的随机数
PrevBlockHash []byte//前区块哈希值' G- I; }# Y' ?4 `' o5 _8 {, E
Data []byte //插入的数据9 `3 j, {* D- [6 h1 k# w' v% w
Hash []byte //当前区块哈希值
}$ \& E5 s& i& K% x/ U
//给到一个创建新区块的方法
func newBlock(data,prehash []byte)*Block {7 z7 p8 j. H, v& h% J' ~) o
block:=Block{
Version:00,8 \) K. y: N% H4 `% M
MerkelRoot:[]byte{},# C2 L1 H# T& s" Z' D, D
TimeStamp:time.Now().Format("2006-15:04:05"),4 W9 b0 W7 k" S7 V7 x
Difficulty:difficulty,1 k H$ g' @( G8 Z2 H: U9 b) z* y
Data:data," \# o8 ? X9 A5 ^3 Z2 H
PrevBlockHash:prehash,
}, |4 }3 ]- a# W8 s0 j$ Q
//需要被挖矿之后才能创建区块,所以调用挖矿函数! N8 j# I! ^6 G
pow:=NewPOW(&block)
nonce,hash:=pow.Mine()
//挖矿结束,得到哈希碰撞值
block.Nonce=nonce
block.Hash=hash
return &block& L. a! B% A6 p+ N. O" v; A7 m& Y
}
//Blockchain模块 `& ^' `% @6 G/ m8 v K
const gnnesinfo="1996年9月2日,一代伟人诞生了"
//给到一个区块链结构( m5 o: Y% S; _
type Blockchain struct {$ E% ?; p% u' \. e, C" K
blocks []*Block
}5 h# N) r% Q. L) U5 u1 r
//将创世区块加入区块链,并返回一条可供操作的区块链
func NewblockChain()*Blockchain {
var bc Blockchain I' `/ W+ v7 X8 c
block:=newBlock([]byte(gnnesinfo),[]byte{})
bc.blocks=append(bc.blocks,block). L$ }3 L2 @4 r
return &bc( R @% \$ u; V; [! W+ Z
}
//给到一个增加区块的方法
func (this *Blockchain)Addblock(data []byte) {% h. ?: @+ {7 Q- M' ]# u' \
lastblockhash:=this.blocks[len(this.blocks)-1].Hash
block:=newBlock(data,lastblockhash)( b1 z9 B/ t' c2 y3 U% r# i
this.blocks=append(this.blocks,block)
}
//遍历,打印所有9 |: g* L* V' p& @1 ?6 p. v
func (this *Blockchain)PrintAll() {
for i,v:=range this.blocks { Z5 g& B/ l. Y7 }* r* s+ r
fmt.Printf("=========区块高度%d=========\n",i)
fmt.Printf("Version : %d\n", v.Version)
fmt.Printf("PrevBlockHash : %x\n", v.PrevBlockHash)
fmt.Printf("Hash : %x\n", v.Hash)
fmt.Printf("MerkleRoot : %x\n", v.MerkelRoot). ]: v: z C6 z# A
fmt.Printf("TimeStamp : %s\n", v.TimeStamp)& x$ f6 Q' N: n2 l7 S5 h0 g
fmt.Printf("Difficuty : %d\n", v.Difficulty); D' t8 w- y3 f1 c/ @$ U
fmt.Printf("Nonce : %d\n", v.Nonce)& U) B3 z+ g! G8 U
fmt.Printf("Data : %s\n", v.Data)& E* W) N& C* k; N8 r& v3 n
}
}/ {) t* W: a2 E2 c e4 w v2 }
//pow挖矿模块8 c9 i5 _8 }3 c2 S' |! D; z
const difficulty=24% o& N+ u; v5 o8 V! m
//POW挖矿结构需要两个参数,一个是所需挖矿的区块,另一个是挖矿成功所需目标数字
type ProofOfWork struct {
target *big.Int
block *Block# g& _% x& A; E( y. Q
}8 S! t3 L* r* u, t
//给到一个根据难度值得到哈希碰撞目标值的函数( R- L2 \' c5 W; s3 T$ r E: Z9 [
func Gettargetint()*big.Int {5 T1 e& ^% s$ X
targetint:=big.NewInt(1)
targetint.Lsh(targetint,256-difficulty)
return targetint
}2 w N7 H, R, F1 ~$ Y+ n
//创建挖矿的方法8 v P6 U9 W. A. z& d; Z/ ^7 y) v
func NewPOW(block *Block)*ProofOfWork {( n) T, N M {/ H( f
var this ProofOfWork
this.block=block
targetint:=Gettargetint()" S5 K& s) Y/ W5 w ]
this.target=targetint' g: f, e+ x& K6 m9 R+ Q
return &this
}
//一个用来将uint64转化为字符切片的小函数,方便接下来的转化
func uint2byte(num uint64)[]byte {: p" @% i/ L# ~
var buff bytes.Buffer+ Z+ d* }9 w1 d
binary.Write(&buff,binary.BigEndian,&num)
return buff.Bytes()" ]% N# [6 L6 c. z7 q, b; J3 v. t7 n
}
//挖矿的准备工作,将其他字符组合起来之后求其哈希值7 a5 I2 s( i p) g+ N
func (pow *ProofOfWork)PreparetoMine(nonce uint64)[]byte {- \9 k% z: T/ T+ c2 U& u3 s6 f& z
info:=[][]byte{
pow.block.PrevBlockHash,1 d9 w1 U6 x- N! \0 H9 N
pow.block.Data,
uint2byte(nonce),
uint2byte(pow.block.Version),+ Y, c& k/ j8 ^2 K( D0 e' X
uint2byte(pow.block.Difficulty),, {( D3 V$ Q- w7 s9 r
[]byte(pow.block.TimeStamp),: l* d4 U( n# G% ?
pow.block.MerkelRoot,
}! O$ N I6 r% s8 w7 }( \/ d: Y
allinfo:=bytes.Join(info,[]byte{}) t& _" S+ Q7 |. z0 E1 Y" k2 `
hash:=sha256.Sum256(allinfo)% @4 T' a. y4 U- n' J/ A
return hash[:]
}9 e4 H, B, y, Z/ b
//pow挖矿方法,返回两个参数,一个是碰撞成功的数字nonce,另一个是当前区块哈希值
func (pow *ProofOfWork)Mine()(uint64,[]byte) {! o2 L- d1 o$ [' N- S
var nonce uint64
//nonce从0开始穷举,直到出现哈希值小于给到的目标值! X' r, }; m% J6 [$ M$ p! K
var hash []byte
for {
hash=pow.PreparetoMine(nonce)
var hashint big.Int
hashint.SetBytes(hash)
//对比哈希值是否小于目标值,小于则成功退出
if hashint.Cmp(pow.target)==-1 {9 s( j6 B' K& s) f) m
break
} l( W1 c6 a! \, O5 _
//不小于则继续穷举
nonce++
}0 {+ _6 d- K: _* w% |7 E
return nonce,hash+ o. J3 f- g1 X7 j7 F1 z$ [
}, Y2 N, W% D8 Q" `
//调用
func main() {4 u1 h) D/ c' ^2 X' a- Y, T3 P4 z
bc:=NewblockChain()
bc.Addblock([]byte("welcometo")), m$ L$ _# Z2 c$ `% \% O9 W1 ]
bc.Addblock([]byte("mycsdnblog"))
bc.PrintAll()
}
以上就是一个微型的区块链了,虽然看起来很简单,但是对于理解比特币、区块链还是有不少帮助的。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
猜你喜欢
成为第一个吐槽的人



