简单区块链的实现(带POW挖矿系统)
蓝天天使2017
发表于 2022-12-7 11:38:58
245
0
0
代码分析" h4 Z, t. b+ T. ^3 A, O2 h
三大模块
代码还是比较简单清晰的,主要有三个模块,Block模块、BlockChain模块、POW模块即挖矿模块。
运行流程
首先从定义一个区块开始,一个区块中包含的信息有区块信息,时间戳,前区块哈希值,现区块哈希值,经过挖矿后得到的哈希碰撞值等等。$ d8 \: @3 h* |. F
接着我们开启一个切片用来存放一个个区块,但是第一个区块是比较特殊的,我们称之为创世区块,在真实的比特币中,第一个区块是由创始人中本聪挖矿所得,没有前哈希值,所以这里我们直接将第一个创世区块创建添加到区块切片中。) |0 N# @3 A6 X0 R( f# y/ [) L
然后给到一个添加区块的方法,用户添加区块信息后,经过POW挖矿系统才能成功添加到区块链上。
有了大概的运行流程接下来再来看代码就会轻松很多了。# y) B9 B/ W J% U
package main, ?; _) s. ]8 c. p4 X% ^) }
import (# j: f. Q `) s1 q4 M
"math/big"
"bytes"
"encoding/binary"
"crypto/sha256"( U1 {6 W' j$ x& c
"fmt"; J4 i9 f$ [( Q: i
"time"7 Q5 U* j% O" k9 C/ C/ z3 c7 g! i
)! x8 V. N' E% K( _2 @, Q8 r& R
//Block模块
type Block struct {2 ?! ]; d7 d; r
Version uint64 //版本号: S4 j" l7 I& N2 f2 L2 J% W
MerkelRoot []byte //这是一个默克尔数,这里先默认为空
TimeStamp string //时间戳
Difficulty uint64 //难度值
Nonce uint64 //挖矿所找到的随机数( o2 D' F3 c1 f: {$ v4 ~3 B" e7 M
PrevBlockHash []byte//前区块哈希值* }# q) f, T; f$ q
Data []byte //插入的数据! h9 J) R% ?9 C$ j v8 s' z
Hash []byte //当前区块哈希值
}
//给到一个创建新区块的方法 K( j8 }& h/ e9 p
func newBlock(data,prehash []byte)*Block {
block:=Block{
Version:00,
MerkelRoot:[]byte{},
TimeStamp:time.Now().Format("2006-15:04:05"),) [8 T1 `" I1 n7 V6 T! P
Difficulty:difficulty,
Data:data,3 [# F# s9 i, ]+ I$ p D' R
PrevBlockHash:prehash,
}
//需要被挖矿之后才能创建区块,所以调用挖矿函数
pow:=NewPOW(&block)0 c7 u8 I" g; K) N; O
nonce,hash:=pow.Mine()
//挖矿结束,得到哈希碰撞值
block.Nonce=nonce7 C% j' `* ?+ S8 d) @
block.Hash=hash3 B: k+ N! f0 }1 ?) Z* \
return &block
}
//Blockchain模块- i" z* v' W* P9 c( ^
const gnnesinfo="1996年9月2日,一代伟人诞生了" 1 ~$ Z& J2 A. u6 k( N
//给到一个区块链结构& v/ s/ c3 R8 T
type Blockchain struct {$ d5 l6 f5 D1 R& R u
blocks []*Block
}+ I( h$ }% k, j: ~9 `
//将创世区块加入区块链,并返回一条可供操作的区块链
func NewblockChain()*Blockchain {* W: K) W6 [9 e3 w) K
var bc Blockchain
block:=newBlock([]byte(gnnesinfo),[]byte{}): n) a4 [- Z8 T y' z; s* X6 I
bc.blocks=append(bc.blocks,block)7 O- t8 |$ P& N; V( b
return &bc
}. ^4 n/ z. V5 J' B
//给到一个增加区块的方法
func (this *Blockchain)Addblock(data []byte) {
lastblockhash:=this.blocks[len(this.blocks)-1].Hash; ~. ` _; a6 P7 p$ b, x7 ?& ^, p
block:=newBlock(data,lastblockhash)- R( x, {+ J% X! Y* e. M
this.blocks=append(this.blocks,block)
}1 D% H& {3 e( D$ X, K
//遍历,打印所有
func (this *Blockchain)PrintAll() {+ Q* k5 m7 u! U: `
for i,v:=range this.blocks { P @8 Y6 |& ~# m# X
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)" l( f2 j/ o/ p$ Z/ h; R8 q* K! Y+ G% z
fmt.Printf("MerkleRoot : %x\n", v.MerkelRoot)8 m! I- P+ ?$ e& A: ?
fmt.Printf("TimeStamp : %s\n", v.TimeStamp)1 K+ A5 q! p( T9 o) m
fmt.Printf("Difficuty : %d\n", v.Difficulty)
fmt.Printf("Nonce : %d\n", v.Nonce)
fmt.Printf("Data : %s\n", v.Data)$ f9 C( n/ b" F' R" b+ S
}
}! O, b% Z! g Z% o0 a, f
//pow挖矿模块& _3 Y/ i: Z- Z& W7 f6 F3 T" ]
const difficulty=243 o' `2 p( ^' @" Q
//POW挖矿结构需要两个参数,一个是所需挖矿的区块,另一个是挖矿成功所需目标数字
type ProofOfWork struct {: v* x' X+ K! l x d
target *big.Int
block *Block
}
//给到一个根据难度值得到哈希碰撞目标值的函数- h3 ^2 D8 A! {- s( O7 L% K
func Gettargetint()*big.Int {
targetint:=big.NewInt(1). @+ ~& X: v9 G
targetint.Lsh(targetint,256-difficulty)
return targetint
}
//创建挖矿的方法
func NewPOW(block *Block)*ProofOfWork {: M' I" P& m7 b. Z2 h, P7 a& k
var this ProofOfWork& _- `2 `4 E. s2 Z" z$ Y
this.block=block
targetint:=Gettargetint()
this.target=targetint
return &this1 }7 E5 B: `' Z8 b$ M/ S: L
}0 c% ?9 A- v# F L
//一个用来将uint64转化为字符切片的小函数,方便接下来的转化# E. F6 P, {# b/ Q( L& w8 P X
func uint2byte(num uint64)[]byte {
var buff bytes.Buffer
binary.Write(&buff,binary.BigEndian,&num)# b; w7 Z+ w, V2 o8 k7 f/ q# a$ Y# n
return buff.Bytes(), t; {# q N5 d6 q& T
}
//挖矿的准备工作,将其他字符组合起来之后求其哈希值
func (pow *ProofOfWork)PreparetoMine(nonce uint64)[]byte {9 g7 ^) J+ {$ x3 h2 }' V9 t/ w( N
info:=[][]byte{6 Q/ X& A7 T' S# `- c% T
pow.block.PrevBlockHash,
pow.block.Data,
uint2byte(nonce),
uint2byte(pow.block.Version),& f3 v) `& d2 j1 Z) R& N$ B
uint2byte(pow.block.Difficulty)," _* a9 H/ F5 C3 l$ C
[]byte(pow.block.TimeStamp), [7 V' }( s+ @7 x4 p: Q# V
pow.block.MerkelRoot,) c+ L3 u* {( O3 d7 \
}. w5 \- F2 Q }1 r* `
allinfo:=bytes.Join(info,[]byte{})
hash:=sha256.Sum256(allinfo)
return hash[:]5 K! i& W" c) v2 p( D& Y- ~ C r
}5 n2 v0 B1 L8 x2 n
//pow挖矿方法,返回两个参数,一个是碰撞成功的数字nonce,另一个是当前区块哈希值
func (pow *ProofOfWork)Mine()(uint64,[]byte) {
var nonce uint64
//nonce从0开始穷举,直到出现哈希值小于给到的目标值
var hash []byte
for {0 d% C5 k4 ]" m/ L% Z; ~. r# f
hash=pow.PreparetoMine(nonce) K7 s d6 }9 @+ o( x$ m9 ]
var hashint big.Int
hashint.SetBytes(hash)
//对比哈希值是否小于目标值,小于则成功退出/ C# z x! k' j
if hashint.Cmp(pow.target)==-1 { N" S& I4 I* _7 w5 u; }* L6 q
break
}
//不小于则继续穷举
nonce++
}! Y. }- E7 J: t$ h
return nonce,hash
}
//调用' k/ d, ` K+ F+ y, R2 v
func main() {
bc:=NewblockChain()5 ~; n5 `' n- j; r/ X0 m% {
bc.Addblock([]byte("welcometo"))1 }" m! k) w2 U
bc.Addblock([]byte("mycsdnblog"))
bc.PrintAll()
}$ J' s! b+ g; I- r# i7 T: D+ P
以上就是一个微型的区块链了,虽然看起来很简单,但是对于理解比特币、区块链还是有不少帮助的。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
猜你喜欢
成为第一个吐槽的人