Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文
最火的热词相必就是区块链了,C++和GO是目前最适合区块链开发的两种语言,所以咱们学GO的肯定得学一点区块链的知识,但是区块链涉及太多密码学,金融学、p2p网络等知识了,从哪里切入呢,今天我们就从用go实现一条带有模拟挖矿系统的简单区块链。
6 K; e1 X7 z( @' `5 Q6 x4 d- g代码分析$ D) l0 b" r* |' n. T3 v: Z9 H
三大模块# j& J# H) v- H1 T0 i0 f: v
代码还是比较简单清晰的,主要有三个模块,Block模块、BlockChain模块、POW模块即挖矿模块。5 Y8 J- u! }$ K
运行流程8 ?* h6 ~4 e; g. B+ g4 E& L
首先从定义一个区块开始,一个区块中包含的信息有区块信息,时间戳,前区块哈希值,现区块哈希值,经过挖矿后得到的哈希碰撞值等等。2 [; I4 L0 i: l$ B$ K
接着我们开启一个切片用来存放一个个区块,但是第一个区块是比较特殊的,我们称之为创世区块,在真实的比特币中,第一个区块是由创始人中本聪挖矿所得,没有前哈希值,所以这里我们直接将第一个创世区块创建添加到区块切片中。1 S& r4 n4 p$ [- @3 t2 {
然后给到一个添加区块的方法,用户添加区块信息后,经过POW挖矿系统才能成功添加到区块链上。) k) j& r; b: f2 ^0 `/ \
有了大概的运行流程接下来再来看代码就会轻松很多了。+ G" C& Q6 M: z% U: M
package main$ K' X2 v7 U& J+ ~4 L% x* X
import ($ T2 v' Z8 n  h
        "math/big"
/ P% }" {# k1 G3 |1 Y2 f% m        "bytes"3 f1 b: b1 p* x% m/ K
        "encoding/binary"
8 x7 [# a3 X' Y$ }# s; H9 x        "crypto/sha256", _; k3 _1 ]& W# t' w. c* t3 J% S
        "fmt"4 `" R3 F' l6 f9 ?' x+ y
        "time"- d* O. v) A9 K! t3 q
): V; G5 y) K$ l1 R
//Block模块1 ]6 Z4 i/ ~2 M: L
type Block struct {& b4 j. E; q# B2 f
        Version uint64                //版本号7 M% b! E. s6 C6 w5 r" e4 C8 X
        MerkelRoot []byte        //这是一个默克尔数,这里先默认为空
: ]* R( o( ~* {. U5 P$ O  `        TimeStamp string         //时间戳5 k! f7 _8 D; W' D% l+ R+ I
        Difficulty uint64        //难度值
* K$ H: ~+ T# M1 l; ~6 j: i# F        Nonce uint64                //挖矿所找到的随机数* x4 a, w/ s" O! Y2 J# C. b
        PrevBlockHash []byte//前区块哈希值
: Q7 T0 R: Z8 V/ i1 g        Data []byte                        //插入的数据
, K9 Y8 a( @* W+ F( Q        Hash []byte                        //当前区块哈希值9 Z% k! P/ D- Z# L* e
}( `- R0 }/ t5 i4 w4 o# j! A! Q
//给到一个创建新区块的方法
6 D' ~/ j6 K) a' Efunc newBlock(data,prehash []byte)*Block  {
3 {0 f4 |& V( ^4 T- ~        block:=Block{
' a/ `! O" r4 Z6 I5 ?9 a: ]                Version:00,  j: ]8 |1 L, g
                MerkelRoot:[]byte{},0 T" T" Z, q% T; @; \8 V
                TimeStamp:time.Now().Format("2006-15:04:05"),9 ?- K- @1 a" b* k7 O0 s
                Difficulty:difficulty,
' M' P8 L+ |6 Q                Data:data,
* D; N8 u4 y, T! R& a                PrevBlockHash:prehash,9 e) @- W  B* C/ Q+ u: M
        }
0 k2 U. I( o# {- E5 U$ W  g        //需要被挖矿之后才能创建区块,所以调用挖矿函数
: u/ e* v' F8 i  [        pow:=NewPOW(&block)) G* C* L$ C$ J+ O
        nonce,hash:=pow.Mine()
5 ~# j( d; O$ U4 m4 \        //挖矿结束,得到哈希碰撞值8 L9 G2 I! X4 F* B5 e( Z' W# d
        block.Nonce=nonce4 j# }* c1 }0 t
        block.Hash=hash  z# d! p) m8 Y5 e
        return &block" n. S) p8 ]6 `, D# {' C$ D9 y
}
# v0 e6 {7 I5 U- \& Z//Blockchain模块% X) k4 H# t9 n$ t+ s% S
const gnnesinfo="1996年9月2日,一代伟人诞生了"
! Z) W' S" ^( T0 g1 D" E$ Y//给到一个区块链结构6 ~* R  G+ r, Z. O% p% |% W: y( u
type Blockchain struct {
6 P' {% i* R1 k: `2 m        blocks []*Block
) K) V; a! O: M$ @: h}
$ Z) B9 c& r1 Q# e+ @. O  s//将创世区块加入区块链,并返回一条可供操作的区块链. {; P" J- w: w% m1 u
func NewblockChain()*Blockchain  {8 ]; S! Y, T  f9 E0 t$ T
        var bc Blockchain3 ]* J  B4 F8 V. t! j
        block:=newBlock([]byte(gnnesinfo),[]byte{})# A1 ~- T; X. @7 {
        bc.blocks=append(bc.blocks,block)0 d5 G1 |1 D4 k4 T  e8 T
        return &bc
: R% x, j7 A* n7 D, D% Z  s}  w) ^( g; i( i% \6 d
//给到一个增加区块的方法/ |" T( ^" k8 C# x# H
func (this *Blockchain)Addblock(data []byte)  {
; h* x  y# I' r( _( G' |8 I                lastblockhash:=this.blocks[len(this.blocks)-1].Hash$ _7 m1 {, v) _/ a
                block:=newBlock(data,lastblockhash)- r6 K5 x; P" I  H, N: O
                this.blocks=append(this.blocks,block). r* v9 ~. D! ~. h- `. d& a
}7 h% Q( p! L9 B$ U4 b  O
//遍历,打印所有1 m9 Q4 _( o! E& j* h/ l+ N
func (this *Blockchain)PrintAll()  {) e" I6 N% h, R9 f
        for i,v:=range this.blocks {
. l6 t  t* e) c! m3 h) d                fmt.Printf("=========区块高度%d=========\n",i), y- }3 d: ~: g! @: g
                fmt.Printf("Version : %d\n", v.Version)
9 `6 e( m, z! P4 x5 @                fmt.Printf("PrevBlockHash : %x\n", v.PrevBlockHash)
( ]. j. S& ^+ m: L$ _5 d9 Y& C# k                fmt.Printf("Hash : %x\n", v.Hash)4 J. y0 t  H7 ]8 _5 D
                fmt.Printf("MerkleRoot : %x\n", v.MerkelRoot)
: j5 {- ~. Q4 m6 K2 I                fmt.Printf("TimeStamp : %s\n", v.TimeStamp)
: x6 n1 J( E3 C/ l" U# M" ]( @                fmt.Printf("Difficuty : %d\n", v.Difficulty)
& Z% r' G9 v; ~                fmt.Printf("Nonce : %d\n", v.Nonce)
  K& l4 l; C# u$ ~  |, [                fmt.Printf("Data : %s\n", v.Data)
5 j3 C% i0 j9 F& Q. k        }
1 E. C" [6 K- s# h2 Q: @}
# L3 h* j' s) ]; e: G. Y//pow挖矿模块" @2 H1 ?5 p4 a2 W: _
const difficulty=24
# D$ z. i* o! [% c( d/ J//POW挖矿结构需要两个参数,一个是所需挖矿的区块,另一个是挖矿成功所需目标数字
" B1 m3 D3 a1 @% C, x; I6 o- v0 F4 `type ProofOfWork struct {
. l  G! Z( F3 j4 @3 Y8 w        target *big.Int
' P; m' N+ P- v        block *Block$ k# h; ?; u# v
}! A6 v5 ]- O! Q, S- C' O" p" D
//给到一个根据难度值得到哈希碰撞目标值的函数% F0 F; V; ~. j3 a: g6 _
func Gettargetint()*big.Int  {7 u/ n% ]% t( S! m) t1 R
        targetint:=big.NewInt(1)7 O4 M" x' n! }' L3 f+ a1 \
        targetint.Lsh(targetint,256-difficulty)  A4 S; E' {  Z7 R* ~
        return targetint
* g$ r9 j9 ~" n3 A0 T! r}) c6 @) z* X  v( c
//创建挖矿的方法
8 k: M9 ~/ Q. O* wfunc NewPOW(block *Block)*ProofOfWork  {5 R5 a% s+ d, J7 q+ i0 s( g) A* f
        var this ProofOfWork0 {$ L4 Y8 G% V7 u/ p
        this.block=block
4 s2 X$ @7 m/ D6 o        targetint:=Gettargetint()' y( K2 n# R- a" g
        this.target=targetint; R1 J4 \8 `5 k" I5 V1 l* P
        return &this6 N- B  S. k2 t% x5 @; D
}) t$ Z8 _  A# ]8 T. d/ {8 q9 b( j
//一个用来将uint64转化为字符切片的小函数,方便接下来的转化
6 T, R# i7 n! j+ J* _func uint2byte(num uint64)[]byte  {
; h8 Z$ i" C1 K- G. ]& u5 F0 ^! P# x        var buff bytes.Buffer
4 ^3 n( ]- S! D) ^2 X        binary.Write(&buff,binary.BigEndian,&num)4 \& o6 d- [" @3 K( b; s3 Y& K
        return buff.Bytes()
/ a' [  r: |, N$ P}$ j( F, [. w- O+ i. i8 A1 {9 u
//挖矿的准备工作,将其他字符组合起来之后求其哈希值
7 [7 Q0 a* q4 I+ f$ Wfunc (pow *ProofOfWork)PreparetoMine(nonce uint64)[]byte {
7 M# B& A3 k; g: T6 X) b5 ?+ c        info:=[][]byte{3 }, _; G$ B* Y
                pow.block.PrevBlockHash,; n1 Q4 O7 T0 _% o
                pow.block.Data,
+ Y: z  x: v: `                uint2byte(nonce),
1 E- f$ Y$ C6 U5 M( u                uint2byte(pow.block.Version),
! T; K9 \9 S, w/ b9 I9 i- ]& N4 N                uint2byte(pow.block.Difficulty),
0 ]( v; b+ `' B$ m: L7 g                []byte(pow.block.TimeStamp),% g6 A9 ?7 h7 h, W; z( V
                pow.block.MerkelRoot,8 F: H- Q8 ]( a2 ]4 p
        }
, y6 I# A5 c( d1 ~9 u8 c/ z        allinfo:=bytes.Join(info,[]byte{})
4 ?( j* c, ~" r1 U# c1 X' q        hash:=sha256.Sum256(allinfo)
; o* Z8 b3 }( v' @. d! S/ Y( C+ X        return hash[:]
, T2 G3 W( Y* Y' ~}- j0 F. ^. T* P6 R! s
//pow挖矿方法,返回两个参数,一个是碰撞成功的数字nonce,另一个是当前区块哈希值+ P; g+ a# b; l$ V" i- X
func (pow *ProofOfWork)Mine()(uint64,[]byte)  {
  j: s5 H, o8 y, u. v& Z  d- j7 E        var nonce uint64
! p8 E+ ]  H. e9 J        //nonce从0开始穷举,直到出现哈希值小于给到的目标值$ F) U3 w$ i5 \$ W- {# V
        var hash []byte
. g. |. s' C( R% I        for  {/ p% r" Q' s, d2 W! D
                hash=pow.PreparetoMine(nonce)
& y* H0 M; n+ c' O0 L# r  n3 t& ^                var hashint big.Int
) \& R+ x0 {4 r. e$ D1 R' |, [3 u/ y                hashint.SetBytes(hash)
! C9 w( e' t, t; T; p7 _                //对比哈希值是否小于目标值,小于则成功退出3 I- C% W' [  X" V' P# i
                if hashint.Cmp(pow.target)==-1 {
: x9 y& ?& D! a5 n6 j9 c                        break( F1 ~# u: L: n- o, G# s6 G
                }
& k( T3 {8 p; E8 Y/ I                //不小于则继续穷举
2 \# m/ z* A: }; Y1 S0 e2 ?                nonce++
3 i. r' Q3 }3 J+ K3 R3 q7 A" o        }6 a+ k- H% x* T! X# u& q
        return nonce,hash0 T: h/ @6 q: `
}
8 W+ L( k$ `' R0 u" U//调用& l7 N. y9 l2 ^: ^, W! d1 Q
func main()  {
% f- F+ B% n; p. ^; N. @bc:=NewblockChain()0 C# B0 s$ `% a% o3 y
bc.Addblock([]byte("welcometo"))( u7 u$ L" r  L7 o. v- a4 }5 z
bc.Addblock([]byte("mycsdnblog"))
4 Q$ t! {$ b2 [' Tbc.PrintAll()$ _6 @' e  x: j2 R
}
6 |1 d5 e4 ^, |* P以上就是一个微型的区块链了,虽然看起来很简单,但是对于理解比特币、区块链还是有不少帮助的。
标签: Pow
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

蓝天天使2017 初中生
  • 粉丝

    0

  • 关注

    0

  • 主题

    10