Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文
最火的热词相必就是区块链了,C++和GO是目前最适合区块链开发的两种语言,所以咱们学GO的肯定得学一点区块链的知识,但是区块链涉及太多密码学,金融学、p2p网络等知识了,从哪里切入呢,今天我们就从用go实现一条带有模拟挖矿系统的简单区块链。
- ^3 g' I. L0 e% z$ S$ Z" T代码分析
4 p4 O9 S; ^0 @# H三大模块' L5 d0 O) F, A% n
代码还是比较简单清晰的,主要有三个模块,Block模块、BlockChain模块、POW模块即挖矿模块。
& u* O: C7 B) v# n9 k  X运行流程! P7 G1 K, q$ z. M  M' c
首先从定义一个区块开始,一个区块中包含的信息有区块信息,时间戳,前区块哈希值,现区块哈希值,经过挖矿后得到的哈希碰撞值等等。' _1 s. F8 `- X) X
接着我们开启一个切片用来存放一个个区块,但是第一个区块是比较特殊的,我们称之为创世区块,在真实的比特币中,第一个区块是由创始人中本聪挖矿所得,没有前哈希值,所以这里我们直接将第一个创世区块创建添加到区块切片中。% i! w8 p5 o; H0 v8 @
然后给到一个添加区块的方法,用户添加区块信息后,经过POW挖矿系统才能成功添加到区块链上。5 l+ W9 F5 V% P  a$ K. f3 f
有了大概的运行流程接下来再来看代码就会轻松很多了。
( m" k6 |1 @9 r: A& ^package main* a; g5 Q  \  A- T2 E" H7 l& B8 [, U
import (( I1 W) Z, J6 n8 b' `  [
        "math/big"
* J6 Z0 T8 c  a" ~6 v8 X- C2 U- `; c        "bytes"; h! M/ }- ?( e$ w( t
        "encoding/binary"
- O$ l$ [) ?# U2 |% c  C$ j        "crypto/sha256"6 [4 M! `, z, ?# x
        "fmt"
% T) h2 S8 }' D$ m' @        "time"
$ [& I& j* p" {5 e)) p9 Y( f7 A3 P; o& s& D
//Block模块. N" n- r+ S6 N. E  J6 G
type Block struct {
) t! p( f1 o2 A8 P4 C2 ?3 b        Version uint64                //版本号) w5 y* G# T. A! D- _$ a
        MerkelRoot []byte        //这是一个默克尔数,这里先默认为空
3 D, t' }$ v  `2 |; a, z        TimeStamp string         //时间戳9 i7 R1 ]( Q+ b+ r
        Difficulty uint64        //难度值9 I% A+ F* o3 t! q
        Nonce uint64                //挖矿所找到的随机数
3 g2 O! _; A# {# m        PrevBlockHash []byte//前区块哈希值
2 v! Q7 p+ }' @) O: r        Data []byte                        //插入的数据; d9 s6 |; i4 P1 h  D& A
        Hash []byte                        //当前区块哈希值
) A( J2 w; v, a# f}
5 Y) q& E+ R  j( _7 R//给到一个创建新区块的方法
: M; Y# p9 b% _) L: s. w/ f: K/ ffunc newBlock(data,prehash []byte)*Block  {% ~, ^% \/ v* I
        block:=Block{
) f9 e- R7 f- g* z                Version:00,8 O1 B( o4 x; O& _$ C& z/ s; m
                MerkelRoot:[]byte{},! ]5 \) G: t" U& D* z+ V
                TimeStamp:time.Now().Format("2006-15:04:05"),+ _- h1 v$ t: u! h: s( J
                Difficulty:difficulty,  P" b3 U8 E0 u
                Data:data,
4 \9 v% d" h5 @                PrevBlockHash:prehash,
" [3 L& t$ X  _/ I  X        }0 h; w7 k9 j$ z7 A5 q6 d" {
        //需要被挖矿之后才能创建区块,所以调用挖矿函数
2 j0 S0 u! P8 D1 J0 P        pow:=NewPOW(&block)! o* e1 y0 }% r+ H, j" ]
        nonce,hash:=pow.Mine()
5 c" k" ~% Z$ N1 R6 F        //挖矿结束,得到哈希碰撞值
8 o& B# ~5 q7 Y% C1 T) }        block.Nonce=nonce  B  L* M8 T$ [) \+ m
        block.Hash=hash
+ |! S7 N2 I1 B        return &block
; Z5 T3 i+ x: ]6 |& I8 Z. J}6 y% U8 X9 M$ z. z% o- {
//Blockchain模块
- u8 n7 z. T8 H$ ~const gnnesinfo="1996年9月2日,一代伟人诞生了" " J% [! O* d, H
//给到一个区块链结构  b; M' `" b+ ?& e
type Blockchain struct {& I, ]' ^* a, E9 R* D, C
        blocks []*Block) W# E  a1 h* \; D% U: [
}# s9 }! I) c$ D  }
//将创世区块加入区块链,并返回一条可供操作的区块链- d6 m. Q" X2 s* B; v# C
func NewblockChain()*Blockchain  {
- t8 r$ w9 f/ h' C, |1 w        var bc Blockchain
) z# ]& t# z% k+ E        block:=newBlock([]byte(gnnesinfo),[]byte{})5 F3 z% y, |2 k- H" l% c% _
        bc.blocks=append(bc.blocks,block)
7 K6 T' Z1 o- d. A        return &bc
* I6 m% P& o' |( r% Y% r. }: K}/ \7 t3 E% E5 S3 U% Z
//给到一个增加区块的方法$ f5 h1 m- i4 |. I" p* X) J# {# L
func (this *Blockchain)Addblock(data []byte)  {
/ g' f( y/ ~: h8 G/ b9 N) N                lastblockhash:=this.blocks[len(this.blocks)-1].Hash
3 j- N( Q0 w9 R* T! w! X                block:=newBlock(data,lastblockhash)
- p2 a. T* E7 z                this.blocks=append(this.blocks,block)
' ~: `: c1 r) m}6 Y( Z  B( W# E( y  `
//遍历,打印所有8 L. L+ T8 ^% H! \/ v9 \* `5 @7 W! Z
func (this *Blockchain)PrintAll()  {5 Q) a0 H. ^$ v% C; l. o2 M# P5 h* O. Z
        for i,v:=range this.blocks {
" l1 R' h5 I4 _1 C0 q0 r1 ^                fmt.Printf("=========区块高度%d=========\n",i)
8 L; k2 D$ n! m: g+ ]6 Z7 o9 A                fmt.Printf("Version : %d\n", v.Version)
2 p" a* F4 j3 D& T; G8 |                fmt.Printf("PrevBlockHash : %x\n", v.PrevBlockHash): i9 w" e* d" `: A! h
                fmt.Printf("Hash : %x\n", v.Hash)- c( G& d! h- r1 w+ U
                fmt.Printf("MerkleRoot : %x\n", v.MerkelRoot)* z. o$ u- `/ g3 p+ e
                fmt.Printf("TimeStamp : %s\n", v.TimeStamp)
* a. |$ |" i4 G4 L' q) ]0 X* F                fmt.Printf("Difficuty : %d\n", v.Difficulty)' @6 u% n+ N; ]2 u2 E$ @, `8 O  j
                fmt.Printf("Nonce : %d\n", v.Nonce)
7 d3 ^  H7 i  e1 v: E8 Q7 {5 [                fmt.Printf("Data : %s\n", v.Data)" X9 Q5 y0 L% @1 F* o9 Z
        }
8 A) {9 R: F9 W}
# M/ v" {5 s2 Z! K9 Q//pow挖矿模块& B8 I) d& y& t' a% D
const difficulty=24
7 j- L! @) _2 D4 f//POW挖矿结构需要两个参数,一个是所需挖矿的区块,另一个是挖矿成功所需目标数字
% u- P8 x. K& s# Mtype ProofOfWork struct {
$ y( x3 n6 U: z% [& W8 E# A" ^        target *big.Int
9 T" r  l8 [" g( U/ w$ `        block *Block& |1 k8 y0 x1 B' }. d
}" |( n2 Y( C# p' Z# U* g  Y
//给到一个根据难度值得到哈希碰撞目标值的函数; G8 C: ^- s+ @4 ]
func Gettargetint()*big.Int  {6 T9 R" g- k( s; s6 O
        targetint:=big.NewInt(1)
, p0 M% M& Y* |) E        targetint.Lsh(targetint,256-difficulty)
5 P4 I' B$ Q- n5 J' B8 q( N        return targetint
# I4 i# C) x( X4 `+ R}- i" \$ k; s2 E% A. {
//创建挖矿的方法
) |  Q9 M8 T) qfunc NewPOW(block *Block)*ProofOfWork  {
* d8 P% h4 B* H& Z2 e# ~4 Q        var this ProofOfWork% V3 ?& `; |3 F. U' L
        this.block=block. A; N/ s+ W6 n" v  g
        targetint:=Gettargetint()$ Q! G, b4 S  b  N( O
        this.target=targetint
: G7 {# _  ?4 j! X( `        return &this5 S! D9 e9 {5 L# V& Z7 E
}* K* O0 b& T6 r! E! h# H9 z
//一个用来将uint64转化为字符切片的小函数,方便接下来的转化7 e3 b% k: U/ e+ B- L0 Z* l' {
func uint2byte(num uint64)[]byte  {% H5 L% \( X. k0 C( V" e! h3 `
        var buff bytes.Buffer5 t* @/ a+ s2 H+ Z# t9 {& V
        binary.Write(&buff,binary.BigEndian,&num)1 f5 k6 M7 c4 b9 x% `
        return buff.Bytes()
8 T: T: I& P& P1 G8 |}" `$ F& i2 K4 G8 }& Z: [8 y
//挖矿的准备工作,将其他字符组合起来之后求其哈希值* f3 H9 \  X$ l# n7 T5 C& t0 `: E
func (pow *ProofOfWork)PreparetoMine(nonce uint64)[]byte {
7 G( @/ Z; N. U4 A        info:=[][]byte{
; W, w6 s2 g8 Z                pow.block.PrevBlockHash,
2 E7 G5 H" p" Z7 A/ U) O) m! @9 j                pow.block.Data,+ G2 a; Q3 a; X& Y
                uint2byte(nonce),
9 P  `: [  g+ |" O3 P% C3 w                uint2byte(pow.block.Version),3 A+ b/ ?1 F* M
                uint2byte(pow.block.Difficulty),
0 I& l0 B2 m, K, Q' l                []byte(pow.block.TimeStamp),
$ n/ r3 u/ i/ t) z* C                pow.block.MerkelRoot,
5 D7 w1 `2 K% T- L  H4 z" X        }
1 h/ X0 B% u% |# Q# f        allinfo:=bytes.Join(info,[]byte{}); }+ f( @$ L0 C+ U
        hash:=sha256.Sum256(allinfo)
) ^& b1 K6 P4 G5 y9 r9 T! A        return hash[:]
/ b) q& R5 L' P, b}7 ^3 W& Q; I7 R- _- o# m) A8 N
//pow挖矿方法,返回两个参数,一个是碰撞成功的数字nonce,另一个是当前区块哈希值4 M  h% i6 r" y6 ~: Y
func (pow *ProofOfWork)Mine()(uint64,[]byte)  {& O1 k: u: {* ]0 E$ |) ]
        var nonce uint64
( u: s8 z) N9 r        //nonce从0开始穷举,直到出现哈希值小于给到的目标值% U$ U& m3 A2 U$ L; F, o0 q) u  y
        var hash []byte( @8 v# A- e! i( B- G6 h
        for  {
8 e" l. s1 c5 d; G                hash=pow.PreparetoMine(nonce)
: n2 }+ u' v7 e) m" `4 f                var hashint big.Int7 A: [$ s* o" ]& ?5 @+ J2 @  {
                hashint.SetBytes(hash)5 o9 y, t" A' O
                //对比哈希值是否小于目标值,小于则成功退出
9 R  _) p: D6 }2 U' T                if hashint.Cmp(pow.target)==-1 {
0 ]2 i) u$ t+ {/ B/ J                        break
7 p0 S) N0 I# q. L" Q; H& a                }
6 e: N6 m2 w% B) ~                //不小于则继续穷举* A) e8 r" U7 r
                nonce+++ i- K4 K- U. a" x( m
        }
; O2 J% }6 q9 S8 D" E' s        return nonce,hash
; N( `- @3 e% A% v5 d0 e+ c}( `7 W& I6 p# n& F5 }5 S
//调用
- M  c. m5 p5 Z7 V+ @: _  O" H7 ofunc main()  {  W& I, Y) F. ^) P8 E5 B
bc:=NewblockChain()
' a1 t$ O1 L) x  d* Mbc.Addblock([]byte("welcometo"))
1 j5 z' ?0 F& w* p6 {bc.Addblock([]byte("mycsdnblog"))0 T; @  V2 l  n/ V$ }
bc.PrintAll()6 u& V! d; M8 y  x# S/ b
}
/ c% w1 V' @7 z& M; M以上就是一个微型的区块链了,虽然看起来很简单,但是对于理解比特币、区块链还是有不少帮助的。
标签: Pow
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

蓝天天使2017 初中生
  • 粉丝

    0

  • 关注

    0

  • 主题

    10