简单区块链的实现(带POW挖矿系统)
蓝天天使2017
发表于 2022-12-7 11:38:58
227
0
0
代码分析
三大模块
代码还是比较简单清晰的,主要有三个模块,Block模块、BlockChain模块、POW模块即挖矿模块。
运行流程: c% `5 f* v* |- N d! Z, Q
首先从定义一个区块开始,一个区块中包含的信息有区块信息,时间戳,前区块哈希值,现区块哈希值,经过挖矿后得到的哈希碰撞值等等。
接着我们开启一个切片用来存放一个个区块,但是第一个区块是比较特殊的,我们称之为创世区块,在真实的比特币中,第一个区块是由创始人中本聪挖矿所得,没有前哈希值,所以这里我们直接将第一个创世区块创建添加到区块切片中。
然后给到一个添加区块的方法,用户添加区块信息后,经过POW挖矿系统才能成功添加到区块链上。4 v k$ R8 _/ I9 M. s* }0 `8 P
有了大概的运行流程接下来再来看代码就会轻松很多了。% y: ?" Y- u$ ]- M' p; J2 O
package main ?7 T3 j% g) Q, S' T
import (
"math/big"
"bytes"
"encoding/binary"
"crypto/sha256"
"fmt"4 G5 U. y# r. @% f
"time"6 a5 l! Y+ H2 F, ~
); W( i- t8 t* h) {5 e: U" E
//Block模块
type Block struct {& m& j5 e: o' }
Version uint64 //版本号! h5 Y' u2 J8 n% Z2 I0 O( E4 w% m0 L
MerkelRoot []byte //这是一个默克尔数,这里先默认为空4 P, E& g3 E8 A) B/ t, @" A% r
TimeStamp string //时间戳. }: [- p) M; |# `
Difficulty uint64 //难度值
Nonce uint64 //挖矿所找到的随机数2 B) _. D G1 X( F' U
PrevBlockHash []byte//前区块哈希值- n9 K1 H5 h. f
Data []byte //插入的数据, m2 z# P) Y! m
Hash []byte //当前区块哈希值$ c2 z* f% X/ c4 j% t) O( l- h- g) U$ h
}) }7 G0 h! f: t" u! @" F/ p3 R0 t
//给到一个创建新区块的方法; ^* e7 m+ r! t3 M/ s# |8 W! i- k) x
func newBlock(data,prehash []byte)*Block {# t5 y: K$ N, U, E( T
block:=Block{
Version:00," I( r, u- [' {
MerkelRoot:[]byte{},# p6 l+ j; b$ g m
TimeStamp:time.Now().Format("2006-15:04:05"),. V6 m0 C5 r& N9 r% h: V
Difficulty:difficulty,
Data:data,
PrevBlockHash:prehash,8 [& ], H4 d8 O4 _4 s: Z- l5 d
}
//需要被挖矿之后才能创建区块,所以调用挖矿函数* ?# }+ u. ]$ x1 M+ I7 |$ ]' ^
pow:=NewPOW(&block)
nonce,hash:=pow.Mine()
//挖矿结束,得到哈希碰撞值8 P8 b% r8 a5 J# d+ H
block.Nonce=nonce2 [7 q5 Q4 P; K! R' e+ b, P7 G
block.Hash=hash
return &block
}* F+ N4 J7 ]% N T- F
//Blockchain模块( B! h' u0 n* i+ r
const gnnesinfo="1996年9月2日,一代伟人诞生了" * S2 B* q3 d) I, y9 f
//给到一个区块链结构/ P3 I: S0 _: s! B- ]2 N2 ?" P1 k- K5 H
type Blockchain struct {4 E3 G: k, T) l4 P0 E4 l1 ^9 m }
blocks []*Block
}' {' B; p+ U" X0 F
//将创世区块加入区块链,并返回一条可供操作的区块链. q( `# u# M _4 d) X' ~
func NewblockChain()*Blockchain {
var bc Blockchain, Z; `6 Y5 I N
block:=newBlock([]byte(gnnesinfo),[]byte{})
bc.blocks=append(bc.blocks,block)
return &bc
}
//给到一个增加区块的方法
func (this *Blockchain)Addblock(data []byte) {. C( g4 t& a6 t
lastblockhash:=this.blocks[len(this.blocks)-1].Hash
block:=newBlock(data,lastblockhash)/ k" w$ S2 Y' \# J( O7 b
this.blocks=append(this.blocks,block)9 } g3 `2 l6 I9 C; g
}1 f1 i# T1 L& w2 Q# y
//遍历,打印所有. L5 n) l& W3 y9 k! z( o$ N
func (this *Blockchain)PrintAll() {
for i,v:=range this.blocks {& `* F: j. {- n8 Q. w0 @, @$ X
fmt.Printf("=========区块高度%d=========\n",i)
fmt.Printf("Version : %d\n", v.Version)+ |3 L6 V$ |" `5 G
fmt.Printf("PrevBlockHash : %x\n", v.PrevBlockHash)
fmt.Printf("Hash : %x\n", v.Hash)6 k* s6 h& K9 M5 B- A1 U
fmt.Printf("MerkleRoot : %x\n", v.MerkelRoot)5 k" F: \( s4 ?8 J$ r
fmt.Printf("TimeStamp : %s\n", v.TimeStamp)
fmt.Printf("Difficuty : %d\n", v.Difficulty)
fmt.Printf("Nonce : %d\n", v.Nonce)' s+ Z# D6 K& \1 r1 o, O1 V
fmt.Printf("Data : %s\n", v.Data)* i( z* G$ _# |
}
}
//pow挖矿模块
const difficulty=24
//POW挖矿结构需要两个参数,一个是所需挖矿的区块,另一个是挖矿成功所需目标数字
type ProofOfWork struct {
target *big.Int
block *Block
}
//给到一个根据难度值得到哈希碰撞目标值的函数& |. r1 [+ o0 {' w
func Gettargetint()*big.Int {
targetint:=big.NewInt(1)0 p6 U( J1 z2 s) B( ]
targetint.Lsh(targetint,256-difficulty)- W# _" F8 }# U3 [8 W* ~
return targetint" l1 P N0 K6 Z2 g
}. T: r% U0 Z: I! ?4 z- O4 |, t& [
//创建挖矿的方法9 M* V) h+ t( K2 p% g# M
func NewPOW(block *Block)*ProofOfWork {6 k9 }+ U; c$ i4 v
var this ProofOfWork
this.block=block8 X4 l2 s% L7 W! n! n: v* L* |0 j
targetint:=Gettargetint()6 O* B' F8 ?- f- Q0 T* z9 X4 j
this.target=targetint
return &this
}6 T# b T2 j4 T" ]% ]
//一个用来将uint64转化为字符切片的小函数,方便接下来的转化3 A5 i; p" W' D- E: {
func uint2byte(num uint64)[]byte {# \& B) f k* \" B4 ?! I# ]* U
var buff bytes.Buffer. B9 e4 @( u1 O+ _2 {
binary.Write(&buff,binary.BigEndian,&num)
return buff.Bytes()
}
//挖矿的准备工作,将其他字符组合起来之后求其哈希值* f! d7 Q2 M$ I
func (pow *ProofOfWork)PreparetoMine(nonce uint64)[]byte {
info:=[][]byte{
pow.block.PrevBlockHash,8 @& }5 B1 y/ X0 f/ m$ M
pow.block.Data,
uint2byte(nonce),
uint2byte(pow.block.Version),1 D9 X* d! S+ Z( K; \# {) o B
uint2byte(pow.block.Difficulty),
[]byte(pow.block.TimeStamp)," ]0 L. W$ u [. Z
pow.block.MerkelRoot,
}
allinfo:=bytes.Join(info,[]byte{})+ U- i% C* C# ]/ B4 T p4 ?0 ?
hash:=sha256.Sum256(allinfo)
return hash[:]
}
//pow挖矿方法,返回两个参数,一个是碰撞成功的数字nonce,另一个是当前区块哈希值4 r3 ]; O& J- J5 ?: e/ W
func (pow *ProofOfWork)Mine()(uint64,[]byte) {
var nonce uint64
//nonce从0开始穷举,直到出现哈希值小于给到的目标值
var hash []byte
for {
hash=pow.PreparetoMine(nonce): H! _' b1 D7 g* E
var hashint big.Int9 t* Y a' x+ W$ g( t* y
hashint.SetBytes(hash)
//对比哈希值是否小于目标值,小于则成功退出
if hashint.Cmp(pow.target)==-1 {
break* `% { k- I* i, m0 |
}- A1 Y$ c* I3 N2 N5 J
//不小于则继续穷举7 F" O5 v3 @( F. s. k, l" n
nonce++
}0 v$ t9 g/ O3 K l2 X8 K- G
return nonce,hash
}
//调用: M$ i! Q" _! ^4 G4 e
func main() {: e% |+ Z5 ~: n/ z+ p" l) H
bc:=NewblockChain()
bc.Addblock([]byte("welcometo")), \, Q$ \ Z* c5 F6 D
bc.Addblock([]byte("mycsdnblog"))
bc.PrintAll(). Z( r6 r, A3 s- o& w# W; o
}/ W: I+ V p' `8 ~
以上就是一个微型的区块链了,虽然看起来很简单,但是对于理解比特币、区块链还是有不少帮助的。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
猜你喜欢
成为第一个吐槽的人