Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文
最火的热词相必就是区块链了,C++和GO是目前最适合区块链开发的两种语言,所以咱们学GO的肯定得学一点区块链的知识,但是区块链涉及太多密码学,金融学、p2p网络等知识了,从哪里切入呢,今天我们就从用go实现一条带有模拟挖矿系统的简单区块链。
5 o4 P2 I3 G; W4 p代码分析" J  t) Q" H! F; }  ?
三大模块# W0 P% o8 X! u, M
代码还是比较简单清晰的,主要有三个模块,Block模块、BlockChain模块、POW模块即挖矿模块。
& B/ ?2 z9 ^& N( w: v运行流程
: B+ X, {2 m- A9 a首先从定义一个区块开始,一个区块中包含的信息有区块信息,时间戳,前区块哈希值,现区块哈希值,经过挖矿后得到的哈希碰撞值等等。
' |- R+ S2 {& l接着我们开启一个切片用来存放一个个区块,但是第一个区块是比较特殊的,我们称之为创世区块,在真实的比特币中,第一个区块是由创始人中本聪挖矿所得,没有前哈希值,所以这里我们直接将第一个创世区块创建添加到区块切片中。
0 A8 A2 y% o% _' x然后给到一个添加区块的方法,用户添加区块信息后,经过POW挖矿系统才能成功添加到区块链上。
8 \, S; A, n; [' N- P2 }. U有了大概的运行流程接下来再来看代码就会轻松很多了。& O$ S  w  c" z& Q" @" @4 ~' u
package main7 t  I0 {7 P- H, [$ e; N
import (
& G! s  J8 M6 X/ W- i# {  ?        "math/big"
& i0 ^/ \8 k, ~2 a$ q        "bytes"
0 i: ^8 N! d% K; e3 x$ v& P        "encoding/binary"
) a  o0 I3 D3 w9 m6 A# y        "crypto/sha256"
  D5 u5 U( T1 [  s( D4 r        "fmt"
5 Z0 H. P* K- V4 t; E+ R2 S        "time"
  x- b/ H* R# @. w% Q* U" Q1 _)
* _4 R7 t! Z, n; U( z" i//Block模块
, {. Y; ]  l4 c, etype Block struct {
  H  S+ M6 T1 C" N  ?        Version uint64                //版本号
- H" s+ R1 b9 R* e% A+ B- _( j8 C        MerkelRoot []byte        //这是一个默克尔数,这里先默认为空2 y" W/ X, K9 u/ r( i. L
        TimeStamp string         //时间戳3 A. F( E) W4 ]2 j1 y) ~7 H% `: p
        Difficulty uint64        //难度值
; |7 b, L2 V$ B4 q        Nonce uint64                //挖矿所找到的随机数1 P; N6 ]! J2 m! w% Y
        PrevBlockHash []byte//前区块哈希值
7 E4 M5 ~) k2 r* m        Data []byte                        //插入的数据
6 M' [5 J" g, G' U8 {8 g" s/ T! m' M        Hash []byte                        //当前区块哈希值
( I4 Q$ u" H7 M}( c$ W( }, b' g( I3 O* n' b
//给到一个创建新区块的方法
. W7 \9 D, N# ^* r4 }+ e, {; s7 qfunc newBlock(data,prehash []byte)*Block  {, t% ]1 p0 O# @) f; i! I
        block:=Block{
1 w$ W8 v! b. i7 B4 ~  H                Version:00,
0 X; j2 l' {4 C' A2 f) B2 A                MerkelRoot:[]byte{},
$ ?* I9 {) |$ M1 w                TimeStamp:time.Now().Format("2006-15:04:05"),
! `2 k0 T2 P; q& y1 y                Difficulty:difficulty,
2 o. {; ^3 t" b( a0 G                Data:data,
. ^# g/ n2 Y" t$ A  B4 x                PrevBlockHash:prehash,
  i1 T& p' E, h1 Y; e( i' a) V4 w9 V        }
0 d! g7 g! f, v& I' L4 \) S9 M        //需要被挖矿之后才能创建区块,所以调用挖矿函数! e# t5 Z: O; F* L
        pow:=NewPOW(&block)
3 d# s2 H! x. C! R% @' l/ o/ t  O        nonce,hash:=pow.Mine(). X9 ~+ f& k" E3 s
        //挖矿结束,得到哈希碰撞值
' g% z. t2 q& t" G        block.Nonce=nonce
& X7 I$ J/ a' N+ P9 a! t        block.Hash=hash5 D$ ^2 \6 N5 _& F9 o
        return &block, U$ W: w3 t. y! x
}
, L7 a; G: M2 {$ y//Blockchain模块
1 e! x# d5 m2 C+ A# m4 Fconst gnnesinfo="1996年9月2日,一代伟人诞生了" 3 Z$ ^5 X/ U8 l( S" C% n
//给到一个区块链结构; y0 b2 G6 ?- |% J2 Y# j- t3 n
type Blockchain struct {' y6 ^2 {8 m4 D
        blocks []*Block
2 O6 K1 D1 b" B: `$ }: E}
% H& q7 i/ h+ I, e! o//将创世区块加入区块链,并返回一条可供操作的区块链
% q) W, `  B1 m1 efunc NewblockChain()*Blockchain  {* l" x2 w* \8 J# v
        var bc Blockchain) R' H' a  z8 g& S
        block:=newBlock([]byte(gnnesinfo),[]byte{})% b7 e3 _4 V/ @; o2 ]/ [
        bc.blocks=append(bc.blocks,block)1 M* c$ \& x  c: p
        return &bc
/ r- l9 H% [+ P0 f9 A" `}
8 d) O' v# ~5 o" b" w//给到一个增加区块的方法* `1 I+ @. c! ^% l
func (this *Blockchain)Addblock(data []byte)  {
" B$ I# P  V* E2 k: D                lastblockhash:=this.blocks[len(this.blocks)-1].Hash
2 c, k3 y( y8 a8 ?                block:=newBlock(data,lastblockhash)
1 F4 r6 D$ ^% X+ N9 \! [! V8 U                this.blocks=append(this.blocks,block)# r  g- [/ |2 [4 G8 C% e
}
$ }+ k# O% I! t( j3 _$ E! e/ C//遍历,打印所有
0 v' `( x4 p- n0 f# Q3 x. c7 P* zfunc (this *Blockchain)PrintAll()  {9 m' _- J. Y  O2 M7 @
        for i,v:=range this.blocks {
2 t2 \* u  E! d. k                fmt.Printf("=========区块高度%d=========\n",i)
+ [; j; R0 Q+ p9 @9 R                fmt.Printf("Version : %d\n", v.Version)
, }! P2 r# H; I7 F- N                fmt.Printf("PrevBlockHash : %x\n", v.PrevBlockHash)
' M% c* [1 Q" l) A- C. u% t' r                fmt.Printf("Hash : %x\n", v.Hash)
9 y1 w$ \* Q& m! s: @  |                fmt.Printf("MerkleRoot : %x\n", v.MerkelRoot)
1 }7 p$ K/ O2 C: u5 w8 E# j7 p  Y, \* q                fmt.Printf("TimeStamp : %s\n", v.TimeStamp)" W4 P5 e% u# ~1 {5 G
                fmt.Printf("Difficuty : %d\n", v.Difficulty)
" @( F5 ?; q" T8 Y                fmt.Printf("Nonce : %d\n", v.Nonce)
* ^4 S: o7 @3 i                fmt.Printf("Data : %s\n", v.Data)) q* m  B* ^! g+ X; Z- Z
        }
6 A% y2 w/ d" ?& I3 V}
) Y0 m- ]. i( R* m: }% [//pow挖矿模块" d5 }  A: o. w5 R% @' C% u
const difficulty=24
/ i2 z2 m' {" ~; z//POW挖矿结构需要两个参数,一个是所需挖矿的区块,另一个是挖矿成功所需目标数字( b3 A/ k& F1 a, s
type ProofOfWork struct {
  V; g  Z! B( |7 n1 T        target *big.Int
6 r; X/ f9 G( A+ A2 s5 l        block *Block8 G% \4 g  I1 O; g# Y. g& M& P
}
( r% @4 O" u0 _9 p4 T//给到一个根据难度值得到哈希碰撞目标值的函数- ]2 S! E/ z/ U: @( z
func Gettargetint()*big.Int  {- h$ h# C6 w; k
        targetint:=big.NewInt(1)3 p' l0 l4 A8 A8 E# f
        targetint.Lsh(targetint,256-difficulty)
' m1 B9 ~. e. d* ^5 f        return targetint- [$ d, n+ j2 E$ m
}
) m% {% x6 U2 m- G3 e! a* H//创建挖矿的方法
+ [$ [. U  v! Y8 O  a# Dfunc NewPOW(block *Block)*ProofOfWork  {) `9 O5 f4 ?3 T1 q+ q1 Q+ L' \
        var this ProofOfWork5 d4 M$ ?& @6 b' |8 k$ q9 ~
        this.block=block) B. Q7 A0 i' V. g
        targetint:=Gettargetint()  y( ^* E! l6 Z2 w1 V* V
        this.target=targetint
/ n" @, Z$ t' H* t; \/ v/ n        return &this9 {  U$ ?- N& g* [3 y
}6 L1 v1 L9 |2 L4 `: g3 P/ J
//一个用来将uint64转化为字符切片的小函数,方便接下来的转化
" c2 O% P6 k3 g  |. ]func uint2byte(num uint64)[]byte  {
/ x4 e% [/ r" r3 d# F* N        var buff bytes.Buffer
- C; Z% x$ r/ }( ?        binary.Write(&buff,binary.BigEndian,&num)
$ Z" A# m" Y( W        return buff.Bytes()' c3 B' `5 ~' M5 q5 e
}+ |1 W; E1 c4 F3 m8 N% `
//挖矿的准备工作,将其他字符组合起来之后求其哈希值
9 C3 W  n6 I( Sfunc (pow *ProofOfWork)PreparetoMine(nonce uint64)[]byte {
3 u0 d: d5 {, J7 A+ M        info:=[][]byte{9 M5 Y/ Y8 V. f/ u5 ^! f
                pow.block.PrevBlockHash,8 i7 M# W( d: c7 Y1 L3 J+ }8 ~
                pow.block.Data,
9 X2 B+ g7 {7 s/ T. l; i                uint2byte(nonce)," \+ _' @* e. z6 t8 K" ~
                uint2byte(pow.block.Version),3 ]/ L: P! E: U, \
                uint2byte(pow.block.Difficulty),
) Z0 Z/ Y9 n8 s0 h) v! o" ^                []byte(pow.block.TimeStamp),
: l6 w  d6 ?9 A' z- x                pow.block.MerkelRoot,
0 b3 J  D+ c* c: F1 V' I, X        }
  y9 q' Q4 ^" A% C        allinfo:=bytes.Join(info,[]byte{})
2 \$ D& f$ l1 f) K& j% N        hash:=sha256.Sum256(allinfo); O; G! O) G% v4 C
        return hash[:]" r3 F" m7 e0 F0 r* |
}7 S! M" _  R) O
//pow挖矿方法,返回两个参数,一个是碰撞成功的数字nonce,另一个是当前区块哈希值
* K* c3 P/ C- u9 ]. v, Efunc (pow *ProofOfWork)Mine()(uint64,[]byte)  {. S  k. S, I5 N
        var nonce uint646 v( Z$ L; W, V
        //nonce从0开始穷举,直到出现哈希值小于给到的目标值! I& L  k; x7 U
        var hash []byte8 x' C) z  V0 D4 J' q
        for  {+ h" X3 ?5 T# H- C& Q5 q4 [
                hash=pow.PreparetoMine(nonce)
: g3 o1 t7 ]# F                var hashint big.Int
/ h( b) \/ I6 a                hashint.SetBytes(hash)
1 e! s. g) {2 B7 ^0 f: ~                //对比哈希值是否小于目标值,小于则成功退出8 o% j0 e2 T) X) v& ~8 K
                if hashint.Cmp(pow.target)==-1 {! _: k7 t1 C6 C8 u
                        break
/ q8 v% U  i; ~/ A                }2 `3 N: D8 m- I2 \, n" A% G4 \9 E
                //不小于则继续穷举$ y  H) Z, J  s, _) v+ P
                nonce++
; G" M, q; G; s. y        }) N+ D5 v# v" m2 k- x8 f+ J8 z
        return nonce,hash' b2 p7 V. L: p+ v5 [
}
. a2 n$ {# I1 S/ b- C; l7 W//调用
9 Y' R( _, f: k7 q9 S( ]3 z3 afunc main()  {
  f) {/ w9 V( N/ n7 |& g4 Qbc:=NewblockChain()- ]0 t( {! c; Z& S6 O7 z
bc.Addblock([]byte("welcometo"))9 m* b4 Y/ E6 g7 J% l  J8 l, y
bc.Addblock([]byte("mycsdnblog"))7 a4 H5 N0 a0 f$ H
bc.PrintAll()% G# }4 I. A- S7 x8 \- i* R  L0 v' R
}0 d; K7 I1 L$ K5 ^2 v" X
以上就是一个微型的区块链了,虽然看起来很简单,但是对于理解比特币、区块链还是有不少帮助的。
标签: Pow
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

蓝天天使2017 初中生
  • 粉丝

    0

  • 关注

    0

  • 主题

    10