天天看點

區塊鍊實戰(一)實作簡單的區塊與區塊鍊交易

區塊鍊實戰

區塊鍊實戰(一)實作簡單的區塊與區塊鍊交易

**注意:**區塊不存儲hash值,節點接受區塊後獨立計算并存儲在本地。

Version 1

區塊相關:

1.定義一個區塊的結構Block

a.區塊頭:6個字段

b.區塊體:字元串表示data

提供一個建立區塊的方法

NewBlock(參數)

區塊鍊相關

定義一個區塊鍊結構BlockChain

Block數組

提供一個建立BlockChain()的方法

NewBlockChain()

提供一個添加區塊的方法

AddBlock(參數)

block.go檔案

package main

import (
    "bytes"
    "crypto/sha256"
    "time"
)

/*
1.定義一個區塊的結構Block
​a.區塊頭:6個字段
​b.區塊體:字元串表示data
*/
//區塊
type Block struct {
    Version int64   //版本
    PerBlockHash []byte //前一個區塊的hash值
    Hash []byte //目前區塊的hash值,是為了簡化代碼
    MerKelRoot []byte  //梅克爾根
    TimeStamp int64  //時間抽
    Bits int64  //難度值
    Nonce int64 //随機值

//區塊體
    Data []byte  //交易資訊
}

/*
提供一個建立區塊的方法
NewBlock(參數)
*/
func NewBlock(data string ,prevBlockHash []byte) *Block {
    var block Block
    block = Block{
        Version:      1,
        PerBlockHash: prevBlockHash,
        //Hash:         []byte{},       //區塊不存儲hash值,節點接受區塊後獨立計算并存儲在本地。
        MerKelRoot:   []byte{},
        TimeStamp:    time.Now().Unix(),
        Bits:         1,
        Nonce:        1,
        Data:         []byte(data),
    }
    block.SetHash()  //填充Hash
    return &block
}

func (block *Block) SetHash() {
    // 源碼裡面是要傳二維切片 func Join(s [][]byte, sep []byte) []byte
    tmp :=[][]byte{
        IntToByte(block.Version),
        block.PerBlockHash,
        block.MerKelRoot,
        IntToByte(block.TimeStamp),
        IntToByte(block.Bits),
        IntToByte(block.Nonce),
    }
    data:=bytes.Join(tmp,[]byte{})    //之後再計算hash
    hash := sha256.Sum256(data)
    block.Hash = hash[:]  //變切片
}


//創始塊
func NewGensisBlock() *Block{
    return NewBlock("Genesis Block!",[]byte{})
}
      

blockChain.go檔案

package main


/*
1. 定義一個區塊鍊結構BlockChain
   Block數組
*/
type BlockChain struct {
   blocks []*Block
}

/*
2. 提供一個建立BlockChain()的方法
   NewBlockChain()
*/
func NewBlockChain() *BlockChain {
   block := NewGensisBlock()
   return &BlockChain{blocks:[]*Block{block}}  //建立隻有一個元素的區塊鍊,初始化
}
/*
3. 提供一個添加區塊的方法
   AddBlock(參數)
*/

func (bc *BlockChain)AddBlock(data string)  {
   PerBlockHash := bc.blocks[len(bc.blocks)-1].Hash  //這一個區塊的哈希是前一塊的哈希值
   block := NewBlock(data,PerBlockHash)
   bc.blocks = append(bc.blocks,block)
}      

utils.go檔案

package main

import (
   "bytes"
   "encoding/binary"
   "fmt"
   "os"
)

func IntToByte(num int64) []byte {
   //func Write(w io.Writer, order ByteOrder, data interface{}) error {
   var buffer bytes.Buffer
   err := binary.Write(&buffer, binary.BigEndian, num)
   CheckErr("IntToByte",err)
   return buffer.Bytes()
}

func CheckErr(position string,err error) {
   if err != nil {
      fmt.Println("error ,pos:",position,err)
      os.Exit(1)
   }
}      

main.go檔案

package main

import "fmt"

func main() {
   bc := NewBlockChain()
   bc.AddBlock("A send B 1BTC")
   bc.AddBlock("B send C 1BTC")
   for _,block := range bc.blocks {
      fmt.Printf("Version : %d\n",block.Version)
      fmt.Printf("PerBlockHash : %x\n",block.PerBlockHash)
      fmt.Printf("Hash : %x\n",block.Hash)
      fmt.Printf("MerKelRoot : %x\n",block.MerKelRoot)
      fmt.Printf("TimeStamp : %d\n",block.TimeStamp)
      fmt.Printf("Bits : %d\n",block.Bits)
      fmt.Printf("Nonce : %d\n",block.Nonce)
      fmt.Printf("Data : %s\n",block.Data)
   }
}      

執行結果

區塊鍊實戰(一)實作簡單的區塊與區塊鍊交易