Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文
最火的热词相必就是区块链了,C++和GO是目前最适合区块链开发的两种语言,所以咱们学GO的肯定得学一点区块链的知识,但是区块链涉及太多密码学,金融学、p2p网络等知识了,从哪里切入呢,今天我们就从用go实现一条带有模拟挖矿系统的简单区块链。( w% h9 y1 U! b0 y9 k' z" ?
代码分析" h4 Z, t. b+ T. ^3 A, O2 h
三大模块
+ w, e0 ^0 W/ ?3 @( H( P! {代码还是比较简单清晰的,主要有三个模块,Block模块、BlockChain模块、POW模块即挖矿模块。
. {) U! l) Z. E# _运行流程
0 W2 E+ c- X9 t! a# G首先从定义一个区块开始,一个区块中包含的信息有区块信息,时间戳,前区块哈希值,现区块哈希值,经过挖矿后得到的哈希碰撞值等等。$ d8 \: @3 h* |. F
接着我们开启一个切片用来存放一个个区块,但是第一个区块是比较特殊的,我们称之为创世区块,在真实的比特币中,第一个区块是由创始人中本聪挖矿所得,没有前哈希值,所以这里我们直接将第一个创世区块创建添加到区块切片中。) |0 N# @3 A6 X0 R( f# y/ [) L
然后给到一个添加区块的方法,用户添加区块信息后,经过POW挖矿系统才能成功添加到区块链上。
0 @1 Y+ A- }( ^& W- k有了大概的运行流程接下来再来看代码就会轻松很多了。# y) B9 B/ W  J% U
package main, ?; _) s. ]8 c. p4 X% ^) }
import (# j: f. Q  `) s1 q4 M
        "math/big"
: q: s+ X% U) A: C! ^9 \. }: z        "bytes"
! E1 i1 z: a3 v0 W/ @& T  w        "encoding/binary"
/ ^. B0 m, i( W7 c2 f& O# {; h        "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模块
1 o/ \- _# ^( }! Otype Block struct {2 ?! ]; d7 d; r
        Version uint64                //版本号: S4 j" l7 I& N2 f2 L2 J% W
        MerkelRoot []byte        //这是一个默克尔数,这里先默认为空
8 G& J: G; M- p# p) L$ ]2 [& W        TimeStamp string         //时间戳
& k( W6 K( q6 |* X3 w        Difficulty uint64        //难度值
  }2 s. i! W' }) |2 k        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                        //当前区块哈希值
/ I  k" A) x" G6 |+ W$ m}
% R7 [6 Y4 f4 r; l' J* a2 W//给到一个创建新区块的方法  K( j8 }& h/ e9 p
func newBlock(data,prehash []byte)*Block  {
7 D& t. }" N- y. `1 _/ |5 r. b        block:=Block{
; Q1 d" W" s: B8 e  H                Version:00,
! \5 }* i8 y3 ?: N8 D# A* V3 g                MerkelRoot:[]byte{},
1 E" G2 A. e1 _* h7 x2 V/ R. M                TimeStamp:time.Now().Format("2006-15:04:05"),) [8 T1 `" I1 n7 V6 T! P
                Difficulty:difficulty,
' r# q; o+ L% S                Data:data,3 [# F# s9 i, ]+ I$ p  D' R
                PrevBlockHash:prehash,
7 J) P( w/ H2 S; r8 w2 {) w        }
: |! V3 G- ?+ [* i8 y        //需要被挖矿之后才能创建区块,所以调用挖矿函数
# |( ]3 B9 P. x- o: l4 P3 W        pow:=NewPOW(&block)0 c7 u8 I" g; K) N; O
        nonce,hash:=pow.Mine()
* F: B3 l! d: c( d8 t        //挖矿结束,得到哈希碰撞值
: {, r0 r" h5 [2 C' A5 o$ z- m( [        block.Nonce=nonce7 C% j' `* ?+ S8 d) @
        block.Hash=hash3 B: k+ N! f0 }1 ?) Z* \
        return &block
4 G9 c- u+ v0 i+ y, p& @+ v}
7 ^# ]8 a( x2 {3 |) E% Z. Y# d//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
! i3 i9 q( S0 e( A( L# n3 F8 q}+ I( h$ }% k, j: ~9 `
//将创世区块加入区块链,并返回一条可供操作的区块链
( F* ?9 T5 p; Z2 H, Y: v4 Jfunc NewblockChain()*Blockchain  {* W: K) W6 [9 e3 w) K
        var bc Blockchain
+ k# L& z6 Q+ w8 E4 G4 O        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
# G$ n1 S$ p8 `}. ^4 n/ z. V5 J' B
//给到一个增加区块的方法
+ N7 \% `* h" k) {8 Ofunc (this *Blockchain)Addblock(data []byte)  {
# A0 S: _9 P+ f: G( J( v                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)
# z" \1 j, Z1 d# h}1 D% H& {3 e( D$ X, K
//遍历,打印所有
6 P. C3 l6 c' \- q+ p2 Wfunc (this *Blockchain)PrintAll()  {+ Q* k5 m7 u! U: `
        for i,v:=range this.blocks {  P  @8 Y6 |& ~# m# X
                fmt.Printf("=========区块高度%d=========\n",i)
7 M( [! j- }5 B& h; g7 D' B                fmt.Printf("Version : %d\n", v.Version)
5 \4 p* u& D# i: W* ~$ v                fmt.Printf("PrevBlockHash : %x\n", v.PrevBlockHash)
7 r  B) r9 v0 x- w  i) Q9 F* W                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)
/ |  J+ s. x4 p$ e/ ]& S' @( @4 M                fmt.Printf("Nonce : %d\n", v.Nonce)
$ ^$ J+ a/ Q, Y7 o  b1 @, O                fmt.Printf("Data : %s\n", v.Data)$ f9 C( n/ b" F' R" b+ S
        }
% _0 O1 I; @3 P* o}! 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挖矿结构需要两个参数,一个是所需挖矿的区块,另一个是挖矿成功所需目标数字
# n( w6 ~6 i; M  b7 [type ProofOfWork struct {: v* x' X+ K! l  x  d
        target *big.Int
) v& W8 U. d  H        block *Block
4 c# t  w# m$ Y4 W}
& g3 i/ K+ O$ X$ N. }//给到一个根据难度值得到哈希碰撞目标值的函数- h3 ^2 D8 A! {- s( O7 L% K
func Gettargetint()*big.Int  {
# V0 g- l" d& L8 _! W: ^2 T        targetint:=big.NewInt(1). @+ ~& X: v9 G
        targetint.Lsh(targetint,256-difficulty)
' q. \" W3 j! t9 ^4 \5 D5 v3 \        return targetint
4 @; v2 W0 U5 h  Z, e}
* ]+ }" P4 D* Y8 r" H//创建挖矿的方法
( }5 Y7 E4 J: b+ n4 `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
7 l- V0 k0 b9 q: Q        targetint:=Gettargetint()
/ J" q: {( c1 C2 D  ^. H  H        this.target=targetint
. ?# y7 o6 Y; t$ j        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  {
, R9 X6 r" N; G        var buff bytes.Buffer
8 @! o# B4 r8 s        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
}
7 D9 O+ B8 W- e2 j& s/ e$ ~//挖矿的准备工作,将其他字符组合起来之后求其哈希值
; B* p8 p% i: U0 Y" q  Zfunc (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,
% K) b* b- _& ~: g! w: `1 R                pow.block.Data,
  Y& G6 i  ?% I7 t3 q; A( @2 A                uint2byte(nonce),
8 ]( N3 Y' g( I. w$ U                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{})
( _! `( Z7 S: X$ y; F" a        hash:=sha256.Sum256(allinfo)
0 p9 W0 K! [+ u        return hash[:]5 K! i& W" c) v2 p( D& Y- ~  C  r
}5 n2 v0 B1 L8 x2 n
//pow挖矿方法,返回两个参数,一个是碰撞成功的数字nonce,另一个是当前区块哈希值
9 ]# Z4 Q4 C1 z$ A0 X3 F5 c" [func (pow *ProofOfWork)Mine()(uint64,[]byte)  {
- P$ g$ _) r% W  u6 O        var nonce uint64
- j3 o, k; a% J' f        //nonce从0开始穷举,直到出现哈希值小于给到的目标值
2 g! B' `7 h$ N% p. U% o/ P$ @/ ^        var hash []byte
0 G" H+ b3 r2 F$ ^( a) h        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
4 r: O0 C: e6 ]7 J                hashint.SetBytes(hash)
3 I3 F0 w3 u/ G                //对比哈希值是否小于目标值,小于则成功退出/ C# z  x! k' j
                if hashint.Cmp(pow.target)==-1 {  N" S& I4 I* _7 w5 u; }* L6 q
                        break
3 K4 |/ X7 x+ {                }
& D! v3 ?2 B8 l+ n8 r0 A  G                //不小于则继续穷举
% g# @$ F1 @" k" ^7 E( u+ j                nonce++
) l2 k; B- @- K1 {+ A: S0 P        }! Y. }- E7 J: t$ h
        return nonce,hash
5 f; N2 ^# w1 O. t}
* g3 M, i' b+ p/ A//调用' k/ d, `  K+ F+ y, R2 v
func main()  {
  e* u7 e' {, ~2 Qbc:=NewblockChain()5 ~; n5 `' n- j; r/ X0 m% {
bc.Addblock([]byte("welcometo"))1 }" m! k) w2 U
bc.Addblock([]byte("mycsdnblog"))
3 }( t. d3 q6 Gbc.PrintAll()
9 ^/ \9 X- M1 E}$ J' s! b+ g; I- r# i7 T: D+ P
以上就是一个微型的区块链了,虽然看起来很简单,但是对于理解比特币、区块链还是有不少帮助的。
标签: Pow
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

蓝天天使2017 初中生
  • 粉丝

    0

  • 关注

    0

  • 主题

    10