Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文
最火的热词相必就是区块链了,C++和GO是目前最适合区块链开发的两种语言,所以咱们学GO的肯定得学一点区块链的知识,但是区块链涉及太多密码学,金融学、p2p网络等知识了,从哪里切入呢,今天我们就从用go实现一条带有模拟挖矿系统的简单区块链。
5 w8 D$ ^9 S; `, X0 D2 \. z, Z& g/ p代码分析
/ ]* z: E" `; E" [4 R$ [7 V( H三大模块
6 v" P! l: s) h, F  p+ f; a. d代码还是比较简单清晰的,主要有三个模块,Block模块、BlockChain模块、POW模块即挖矿模块。
% w7 c- u5 C  B3 }8 @# V# H运行流程: c% `5 f* v* |- N  d! Z, Q
首先从定义一个区块开始,一个区块中包含的信息有区块信息,时间戳,前区块哈希值,现区块哈希值,经过挖矿后得到的哈希碰撞值等等。
1 g- u0 ~, C# ^# W3 t接着我们开启一个切片用来存放一个个区块,但是第一个区块是比较特殊的,我们称之为创世区块,在真实的比特币中,第一个区块是由创始人中本聪挖矿所得,没有前哈希值,所以这里我们直接将第一个创世区块创建添加到区块切片中。
7 [. c" {, y5 n# v) M: ]然后给到一个添加区块的方法,用户添加区块信息后,经过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 (
7 E( f) t2 a0 F4 {        "math/big"
( E! `  r7 g( y5 E        "bytes"
3 w" [# Y, g6 G. L* i, ?        "encoding/binary"
0 O7 |: q5 p; Y" R  F2 {        "crypto/sha256"
1 I3 p( [+ b' o0 h        "fmt"4 G5 U. y# r. @% f
        "time"6 a5 l! Y+ H2 F, ~
); W( i- t8 t* h) {5 e: U" E
//Block模块
) Z+ @4 z3 I1 O4 N. wtype 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        //难度值
/ n5 Q" a9 T5 J! l  c        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{
* C! j2 A( R& x- m                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,
/ K$ ]+ F$ d8 T: G                Data:data,
! ?- o2 L$ ^$ t1 D                PrevBlockHash:prehash,8 [& ], H4 d8 O4 _4 s: Z- l5 d
        }
; X1 s. D- x5 M& u% k1 e        //需要被挖矿之后才能创建区块,所以调用挖矿函数* ?# }+ u. ]$ x1 M+ I7 |$ ]' ^
        pow:=NewPOW(&block)
4 n; J( O& E( N3 K; M( _        nonce,hash:=pow.Mine()
) ~: [& G: W6 _( P8 H        //挖矿结束,得到哈希碰撞值8 P8 b% r8 a5 J# d+ H
        block.Nonce=nonce2 [7 q5 Q4 P; K! R' e+ b, P7 G
        block.Hash=hash
9 r3 r  J4 H% [( f9 P+ h' r        return &block
- _0 i4 Q) v- I" U! z3 R. p}* 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
" r* R# j3 k9 m- j5 I}' {' B; p+ U" X0 F
//将创世区块加入区块链,并返回一条可供操作的区块链. q( `# u# M  _4 d) X' ~
func NewblockChain()*Blockchain  {
8 R/ Z8 b# T/ W1 a, y        var bc Blockchain, Z; `6 Y5 I  N
        block:=newBlock([]byte(gnnesinfo),[]byte{})
* H( x8 c7 o! l, U        bc.blocks=append(bc.blocks,block)
& G) r) p$ G( e# W# V0 X% ?: l        return &bc
8 P; h7 P7 u# B- Z2 q9 k2 F+ F- K}
. p- a2 `7 \4 b3 [: J9 Z* c//给到一个增加区块的方法
: t: ]9 `! \% g4 Jfunc (this *Blockchain)Addblock(data []byte)  {. C( g4 t& a6 t
                lastblockhash:=this.blocks[len(this.blocks)-1].Hash
2 t. s& p# w2 p6 e2 p, w, b                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()  {
9 `! P; ?+ s$ h) ^: g        for i,v:=range this.blocks {& `* F: j. {- n8 Q. w0 @, @$ X
                fmt.Printf("=========区块高度%d=========\n",i)
' q, I2 C  R3 s4 C4 g' N                fmt.Printf("Version : %d\n", v.Version)+ |3 L6 V$ |" `5 G
                fmt.Printf("PrevBlockHash : %x\n", v.PrevBlockHash)
. ?6 K5 e# |& Z& l/ M                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)
* i/ g+ d$ |$ Y# A1 R9 v4 z                fmt.Printf("Difficuty : %d\n", v.Difficulty)
5 t7 y+ D' T/ v1 p- a$ j                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$ _# |
        }
" o" D4 l5 e' B2 L' K$ d}
$ u  e/ q  z6 j- x6 h//pow挖矿模块
. e  @' D. K8 u: S0 r, f# e! jconst difficulty=24
& s; D. z: R: X0 Q7 _- \: N$ Q1 r//POW挖矿结构需要两个参数,一个是所需挖矿的区块,另一个是挖矿成功所需目标数字
. a$ F) [% p; U) n7 vtype ProofOfWork struct {
4 p! A) \8 ~5 p        target *big.Int
$ ~6 L! p* Y7 X9 y* P; }1 v" Q$ a        block *Block
/ E) t/ t+ D" E& [* U5 h}
! }# G* d- n) J8 m* d//给到一个根据难度值得到哈希碰撞目标值的函数& |. r1 [+ o0 {' w
func Gettargetint()*big.Int  {
  O0 {( X4 ~  Y$ |+ o        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
# T7 {8 T' I  {5 y  K3 @, ^$ A        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
8 P( Y$ U2 Y/ }& F        return &this
8 K8 J$ E" p/ w6 Q6 ]4 ]}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)
0 l3 u$ p4 X' P/ @) U        return buff.Bytes()
5 _$ h& V/ B" _1 a}
" W, @3 k4 o, W5 ?7 M% g, c: W//挖矿的准备工作,将其他字符组合起来之后求其哈希值* f! d7 Q2 M$ I
func (pow *ProofOfWork)PreparetoMine(nonce uint64)[]byte {
  Q- t3 R; P3 r# H        info:=[][]byte{
" `3 L! t0 B' {8 O  _                pow.block.PrevBlockHash,8 @& }5 B1 y/ X0 f/ m$ M
                pow.block.Data,
9 g% _, _2 f+ {9 E) |; M! X                uint2byte(nonce),
8 w( I8 ^5 J$ s# Y6 y& m                uint2byte(pow.block.Version),1 D9 X* d! S+ Z( K; \# {) o  B
                uint2byte(pow.block.Difficulty),
/ w) g! X. r( U3 l                []byte(pow.block.TimeStamp)," ]0 L. W$ u  [. Z
                pow.block.MerkelRoot,
6 c7 n5 i. i9 I+ _        }
; c# ?. w" R# F/ b; Y        allinfo:=bytes.Join(info,[]byte{})+ U- i% C* C# ]/ B4 T  p4 ?0 ?
        hash:=sha256.Sum256(allinfo)
8 P4 ?% w: O" L7 S/ x% U: N( t        return hash[:]
: L7 y1 r+ ~7 l/ a+ J! s}
, U  u+ G% L/ e7 X  Z. X! ?6 N//pow挖矿方法,返回两个参数,一个是碰撞成功的数字nonce,另一个是当前区块哈希值4 r3 ]; O& J- J5 ?: e/ W
func (pow *ProofOfWork)Mine()(uint64,[]byte)  {
  M: N! X( k/ b) u        var nonce uint64
2 k7 s) J' f& \9 g7 C        //nonce从0开始穷举,直到出现哈希值小于给到的目标值
! @3 @5 R  a3 k+ t% H1 _- v        var hash []byte
" `+ d, O/ ~: t# K3 W0 q9 [& X- a        for  {
3 r2 E2 s0 i4 d/ ]6 `* _$ D! P                hash=pow.PreparetoMine(nonce): H! _' b1 D7 g* E
                var hashint big.Int9 t* Y  a' x+ W$ g( t* y
                hashint.SetBytes(hash)
, c  Q, N" f: [                //对比哈希值是否小于目标值,小于则成功退出
3 z3 p# I: P6 ~2 h                if hashint.Cmp(pow.target)==-1 {
" r8 l( V% E% `9 P                        break* `% {  k- I* i, m0 |
                }- A1 Y$ c* I3 N2 N5 J
                //不小于则继续穷举7 F" O5 v3 @( F. s. k, l" n
                nonce++
3 f* m* Y, `( k- F        }0 v$ t9 g/ O3 K  l2 X8 K- G
        return nonce,hash
7 O- \5 p+ L0 z9 c' \}
1 B: L- W& _; `//调用: M$ i! Q" _! ^4 G4 e
func main()  {: e% |+ Z5 ~: n/ z+ p" l) H
bc:=NewblockChain()
8 w+ I" V/ B, Qbc.Addblock([]byte("welcometo")), \, Q$ \  Z* c5 F6 D
bc.Addblock([]byte("mycsdnblog"))
  b( _" |. N/ l" {bc.PrintAll(). Z( r6 r, A3 s- o& w# W; o
}/ W: I+ V  p' `8 ~
以上就是一个微型的区块链了,虽然看起来很简单,但是对于理解比特币、区块链还是有不少帮助的。
标签: Pow
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

蓝天天使2017 初中生
  • 粉丝

    0

  • 关注

    0

  • 主题

    10