標籤:range return evb win version 擷取 ash data 校正
block.go
package mainimport ( "time")//定義塊結構type Block struct{ Version int64 PrevBlockHash []byte Hash []byte TimeStamp int64 TargetBits int64 Nonce int64 MerKelRoot []byte Data []byte}//設定建立塊的方法func NewBlock(data string, prevBlockHash []byte) *Block{ block := &Block{ Version:1, PrevBlockHash:prevBlockHash, //Hash: TimeStamp:time.Now().Unix(), TargetBits:10, Nonce:0, MerKelRoot:[]byte{}, Data:[]byte(data), } //block.SetHash() //設定區塊的雜湊值--->>> v2中來自工作量證明 pow := NewProofOfWork(block) nonce, hash := pow.Run() block.Hash = hash block.Nonce = nonce return block}// 添加雜湊值---->> v2中來自pow//func (block *Block)SetHash(){// tmp := [][]byte{// //實現int類型轉換為byte類型的工具函數// IntToByte(block.Version),// block.PrevBlockHash,// IntToByte(block.TimeStamp),// block.MerKelRoot,// IntToByte(block.Nonce),// block.Data,// }// //將區塊的各個欄位連結成一個切片,使用【】byte{}進行連結,目的是避免汙染源區塊的資訊// data := bytes.Join(tmp,[]byte{})//// //對區塊進行sha256雜湊演算法,傳回值為[32]byte數組,不是切片// hash := sha256.Sum256(data)// block.Hash = hash[:]//由數群組轉換為切片//}// 創世塊的建立,它的錢一個去魁岸的雜湊值為空白func NewGenesisBlock() *Block{ return NewBlock("Genesis Block!",[]byte{})}
blockchain.go
package mainimport "os"//定義區塊鏈條type BlockChain struct{ blocks []*Block}// 建立區塊鏈,並且添加創世塊func NewBlockChain() *BlockChain{ return &BlockChain{[]*Block{ NewGenesisBlock(), }}}//添加區塊func (bc *BlockChain)AddBlock(data string){ //簡單校正 if len(bc.blocks) <= 0 { os.Exit(1) } //根據上一區塊,建立新的區塊 lastblock := bc.blocks[len(bc.blocks)-1] prevBlockHash := lastblock.Hash block := NewBlock(data, prevBlockHash) //添加到區塊鏈當中 bc.blocks = append(bc.blocks, block)}
utils
package mainimport ( "bytes" "encoding/binary" "fmt" "os")func IntToByte(num int64)[]byte{ var buffer bytes.Buffer err := binary.Write(&buffer, binary.BigEndian, num) //if err != nil{ // fmt.Println("IntToByte err occur:",err) // os.Exit(1) //} CheckErr(err) return buffer.Bytes()}func CheckErr(err error){ if err != nil{ fmt.Println("err occur:",err) os.Exit(1) }}
proofOfWork.go
package mainimport ( "math/big" "bytes" "math" "crypto/sha256" "fmt")const targetBits = 24 //假定難度值type ProofOfWork struct{ block *Block targetBit *big.Int}func NewProofOfWork(block *Block) *ProofOfWork{ var IntTarget = big.NewInt(1) // 假定值 //000000000000000000000000000000001 初始值 //100000000000000000000000000000000 十進位 //000000000100000000000000000000000 十進位 //000001000000000000000000000000000 十六進位 目標雜湊值 //0000000a0000000000001234560000000 實際值 IntTarget.Lsh(IntTarget, uint(256- targetBits)) return &ProofOfWork{block,IntTarget}}func (pow *ProofOfWork)PrepareRawData(nonce int64) []byte{ block := pow.block //擷取需要處理的區塊 tmp := [][]byte{ //實現int類型轉換為byte類型的工具函數 IntToByte(block.Version), block.PrevBlockHash, IntToByte(block.TimeStamp), block.MerKelRoot, IntToByte(nonce), IntToByte(targetBits), //添加難度值 block.Data, } //將區塊的各個欄位連結成一個切片,使用【】byte{}進行連結,目的是避免汙染源區塊的資訊 data := bytes.Join(tmp,[]byte{}) return data}func (pow *ProofOfWork)Run()(int64, []byte){ var nonce int64 var hash [32]byte var HashInt big.Int fmt.Println("Begin Minng ...") fmt.Printf("target hash : %x\n", pow.targetBit.Bytes()) for nonce < math.MaxInt64{ data := pow.PrepareRawData(nonce) hash = sha256.Sum256(data) //取出來後是字串 HashInt.SetBytes(hash[:]) //將byte值轉換為大的數字 // 比較雜湊值 if HashInt.Cmp(pow.targetBit) == -1{ fmt.Printf("Found Hash:%x\n", hash) break }else{ nonce ++ } } return nonce, hash[:]}//提供外部校正的方法func (pow *ProofOfWork)IsValid()bool{ data :=pow.PrepareRawData(pow.block.Nonce) hash := sha256.Sum256(data) var IntHash big.Int IntHash.SetBytes(hash[:]) return IntHash.Cmp(pow.targetBit) == -1}
main.go
package mainimport "fmt"func main(){ bc := NewBlockChain() bc.AddBlock("班長轉給老師一枚比特幣") bc.AddBlock("班長又轉給老師一枚比特幣") for i, block := range bc.blocks{ fmt.Println("====block num:", i) fmt.Printf("Data:%s\n", block.Data) fmt.Println("Version:",block.Version) fmt.Printf("PrevHash:%x\n",block.PrevBlockHash) fmt.Printf("Hash:%x\n",block.TimeStamp) fmt.Printf("TimeStamp:%d\n",block.TimeStamp) fmt.Printf("MerKel:%x\n",block.MerKelRoot) fmt.Printf("Nonce:%d\n",block.Nonce) // pow := NewProofOfWork(block) fmt.Printf("IsvALID:%v\n",pow.IsValid()) }}
最終啟動並執行效果如下所示:
Begin Minng ...target hash : 010000000000000000000000000000000000000000000000000000000000Found Hash:00000014312c76058b55905dbf9915019c484df5f64b9655d01985e050e16eddBegin Minng ...target hash : 010000000000000000000000000000000000000000000000000000000000Found Hash:000000d3c28e9cff07f43949c6c6f23444c1beb7494aebb3be5cf74614e77f04Begin Minng ...target hash : 010000000000000000000000000000000000000000000000000000000000Found Hash:0000004b9205eab846bcf921c952ea2a91e103a4c37170304c4e1bb85d32d73e====block num: 0Data:Genesis Block!Version: 1PrevHash:Hash:5bd09d11TimeStamp:1540398353MerKel:Nonce:26865217IsvALID:true====block num: 1Data:班長轉給老師一枚比特幣Version: 1PrevHash:00000014312c76058b55905dbf9915019c484df5f64b9655d01985e050e16eddHash:5bd09d35TimeStamp:1540398389MerKel:Nonce:6908425IsvALID:true====block num: 2Data:班長又轉給老師一枚比特幣Version: 1PrevHash:000000d3c28e9cff07f43949c6c6f23444c1beb7494aebb3be5cf74614e77f04Hash:5bd09d42TimeStamp:1540398402MerKel:Nonce:70302967IsvALID:true
建立區塊鏈之v2實現pow(ProofOfWork工作量證明)