简单区块链的实现(带POW挖矿系统)
蓝天天使2017
发表于 2022-12-7 11:38:58
135
0
0
代码分析
三大模块
代码还是比较简单清晰的,主要有三个模块,Block模块、BlockChain模块、POW模块即挖矿模块。
运行流程
首先从定义一个区块开始,一个区块中包含的信息有区块信息,时间戳,前区块哈希值,现区块哈希值,经过挖矿后得到的哈希碰撞值等等。, J0 x( I3 h6 [7 h& |# u) R3 E7 x
接着我们开启一个切片用来存放一个个区块,但是第一个区块是比较特殊的,我们称之为创世区块,在真实的比特币中,第一个区块是由创始人中本聪挖矿所得,没有前哈希值,所以这里我们直接将第一个创世区块创建添加到区块切片中。& B& c! g c1 Q1 i; Q$ Q! T
然后给到一个添加区块的方法,用户添加区块信息后,经过POW挖矿系统才能成功添加到区块链上。
有了大概的运行流程接下来再来看代码就会轻松很多了。; r* ] d3 D1 E; m' T1 m7 A
package main8 Z+ j( g7 i/ A/ L0 S" Z' {/ ^
import (/ x2 J5 T2 ^* j
"math/big"7 t6 J' E. S. q! T
"bytes"
"encoding/binary": U `' G! F+ d% S4 L P( S
"crypto/sha256"
"fmt"
"time"5 N3 M: a' S" l* o4 D
)* r, C, y% N, h$ d h
//Block模块" H2 @& M6 y/ }6 M! N
type Block struct {6 r* N0 @9 M" t e: @& [
Version uint64 //版本号
MerkelRoot []byte //这是一个默克尔数,这里先默认为空
TimeStamp string //时间戳
Difficulty uint64 //难度值5 W D( j' X* ~
Nonce uint64 //挖矿所找到的随机数5 ~# l! p8 V7 p% u
PrevBlockHash []byte//前区块哈希值& ~% `& v, K' [( n& M
Data []byte //插入的数据. j2 j: {2 L8 d7 Q) l
Hash []byte //当前区块哈希值
}3 {' L; e& y2 i( m: l3 z. @4 N
//给到一个创建新区块的方法, J) l* z- Y, D7 L
func newBlock(data,prehash []byte)*Block {
block:=Block{8 e* ]+ w( ?% a3 p" ^
Version:00,- ?! z# V' ~" `
MerkelRoot:[]byte{},
TimeStamp:time.Now().Format("2006-15:04:05"),! \. X% ~0 l9 t8 y- ]
Difficulty:difficulty,$ @' b) ~/ J1 H* P$ Y5 G7 H6 K
Data:data,
PrevBlockHash:prehash,
}
//需要被挖矿之后才能创建区块,所以调用挖矿函数) J+ b1 e7 y9 M( s! c, {& q
pow:=NewPOW(&block)9 J' z2 t# f! b- K! ~& J7 Y
nonce,hash:=pow.Mine()
//挖矿结束,得到哈希碰撞值
block.Nonce=nonce
block.Hash=hash4 m% q; n' ?* N( m& h
return &block
} _ e: s) [& P4 A
//Blockchain模块
const gnnesinfo="1996年9月2日,一代伟人诞生了"
//给到一个区块链结构
type Blockchain struct {1 Z0 w* l: T0 d0 v' \' ]
blocks []*Block, {8 U3 n, n- \0 h
}
//将创世区块加入区块链,并返回一条可供操作的区块链
func NewblockChain()*Blockchain {
var bc Blockchain
block:=newBlock([]byte(gnnesinfo),[]byte{})
bc.blocks=append(bc.blocks,block)# K: b) E3 S1 _% A
return &bc
}
//给到一个增加区块的方法8 b3 }( D. g. w
func (this *Blockchain)Addblock(data []byte) {
lastblockhash:=this.blocks[len(this.blocks)-1].Hash
block:=newBlock(data,lastblockhash)
this.blocks=append(this.blocks,block)
}8 ?3 T, J7 J. L4 H( m; u3 {* j
//遍历,打印所有% c0 o9 d' w9 g. I4 c4 P8 Q
func (this *Blockchain)PrintAll() {/ S+ {+ s) W" f, |
for i,v:=range this.blocks {
fmt.Printf("=========区块高度%d=========\n",i)
fmt.Printf("Version : %d\n", v.Version)
fmt.Printf("PrevBlockHash : %x\n", v.PrevBlockHash)( f5 _3 o$ b# k0 Y% z o
fmt.Printf("Hash : %x\n", v.Hash)
fmt.Printf("MerkleRoot : %x\n", v.MerkelRoot)
fmt.Printf("TimeStamp : %s\n", v.TimeStamp)1 E, k7 B$ q' `0 C
fmt.Printf("Difficuty : %d\n", v.Difficulty)& |7 N" I8 @; N- g. z
fmt.Printf("Nonce : %d\n", v.Nonce)
fmt.Printf("Data : %s\n", v.Data)% A( ]0 C. [) m1 C1 y
}
}% |9 P" v; V2 B/ Z
//pow挖矿模块
const difficulty=24
//POW挖矿结构需要两个参数,一个是所需挖矿的区块,另一个是挖矿成功所需目标数字
type ProofOfWork struct {+ ]7 W, H% L* c1 _( C
target *big.Int
block *Block
}
//给到一个根据难度值得到哈希碰撞目标值的函数
func Gettargetint()*big.Int {
targetint:=big.NewInt(1)
targetint.Lsh(targetint,256-difficulty)7 M4 ^8 o2 P) m
return targetint5 U. Y+ y" U3 W+ F* J# `# K6 _2 C6 Z
}
//创建挖矿的方法
func NewPOW(block *Block)*ProofOfWork {( @7 I1 l( v( L; _$ A
var this ProofOfWork
this.block=block% C; E, h" Z1 {4 P' q' a
targetint:=Gettargetint()
this.target=targetint; P1 Q3 F0 t& {' m/ d( M
return &this/ ^$ o1 _% Q* x* S6 z
}# `3 V+ k" e2 J& x( e' a* `
//一个用来将uint64转化为字符切片的小函数,方便接下来的转化# U1 W) O& ~% O/ g( D4 m$ o
func uint2byte(num uint64)[]byte {
var buff bytes.Buffer( F, C/ K( _/ N O% p1 S1 N
binary.Write(&buff,binary.BigEndian,&num)
return buff.Bytes()+ @/ Z" D& d6 i# P7 p
}
//挖矿的准备工作,将其他字符组合起来之后求其哈希值
func (pow *ProofOfWork)PreparetoMine(nonce uint64)[]byte {
info:=[][]byte{
pow.block.PrevBlockHash,( ^3 Q1 z, J3 ~, }
pow.block.Data,' T k* E& H9 y4 n) s* f2 L
uint2byte(nonce),& _1 o9 b$ O0 [0 A3 G; f- ?) l
uint2byte(pow.block.Version),) v9 f% y: X3 b& D
uint2byte(pow.block.Difficulty),, E" ~/ p9 b t% F! j' |2 @1 n/ \
[]byte(pow.block.TimeStamp),. r d; w. l( o; X: ?
pow.block.MerkelRoot," J2 N6 J+ ?( K* W: Y B
}! J9 M k8 ]7 s! k/ X+ X( e
allinfo:=bytes.Join(info,[]byte{})# Q! s5 s9 s* i4 [+ f' M4 r( W
hash:=sha256.Sum256(allinfo)
return hash[:]& |/ M8 a( o2 J3 {$ D# u
}
//pow挖矿方法,返回两个参数,一个是碰撞成功的数字nonce,另一个是当前区块哈希值+ `0 r) S z) {: }! N$ j/ \0 w
func (pow *ProofOfWork)Mine()(uint64,[]byte) {
var nonce uint64- S) L$ l* k) z$ b$ G9 J
//nonce从0开始穷举,直到出现哈希值小于给到的目标值9 m2 A- H: H$ A! E- Q1 q/ D) @
var hash []byte' q6 w z* O/ X% E$ _3 D* `" i4 p* B6 @1 a
for {" X- @7 O8 Y# k6 t
hash=pow.PreparetoMine(nonce)- o* i" }' S. C: E$ U
var hashint big.Int
hashint.SetBytes(hash)
//对比哈希值是否小于目标值,小于则成功退出* r2 q% U7 C9 Q" [* x" ]
if hashint.Cmp(pow.target)==-1 {2 Q! S9 l+ X: |% k2 e: h' Z
break6 E- D; D; T4 c- L# Q; [ t0 O
}4 |% S8 B a6 p: k0 D5 y: J2 a
//不小于则继续穷举+ h, k6 U7 P2 b* m9 R( m
nonce++
}
return nonce,hash8 E% u- {( [0 w- ~' U: I3 I
}
//调用
func main() {- n9 d7 {3 E# e; ?9 M9 T
bc:=NewblockChain()
bc.Addblock([]byte("welcometo")); ^' B7 U# g8 O0 ]6 E W- g0 X1 n
bc.Addblock([]byte("mycsdnblog"))% S7 k6 z8 o& e8 a6 v* f
bc.PrintAll()
}
以上就是一个微型的区块链了,虽然看起来很简单,但是对于理解比特币、区块链还是有不少帮助的。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
猜你喜欢
成为第一个吐槽的人