区块链/BlockChain+ProofOfWork

#区块的定义和操作

#链的定义和操作

#工作量证明

//main.go

package main

import "fmt"

func main(){
	fmt.Println("=======================")
	bc := NewBlockChain()

	t1 := Transactions{[]byte("111"),[]byte("a send b 1 BTC")}
	t2 := Transactions{[]byte("222"),[]byte("b send c 1 BTC")}

	bc.AddBlock(&t1)
	bc.AddBlock(&t2)

	fmt.Println()
	bc.Print()
}

 

//chain.go

package main

import "fmt"

type BlockChain struct{
	blocks []*Block
}

func NewBlockChain() *BlockChain{
	block := NewGenesisBlock()
	chain := BlockChain{
		blocks:[]*Block{block},
	}
	return &chain
}


func (chain *BlockChain) AddBlock(body *Transactions){
	prevBlockHash := chain.blocks[len(chain.blocks)-1].Hash
	block := NewBlock(string(body.Coinbase),string(body.Data),prevBlockHash)

	chain.blocks = append(chain.blocks,block)
}

func (chain *BlockChain) Print(){
	for _,data := range chain.blocks{
		fmt.Printf("Version %d\n",data.Version)
		fmt.Printf("PrevBlockHash %x\n",string(data.PrevBlockHash))
		fmt.Printf("MerKelRoot %x\n",string(data.MerKelRoot))
		fmt.Printf("TimeStamp %d\n",data.TimeStamp)
		fmt.Printf("Bits %d\n",data.Bits)
		fmt.Printf("Nonce %d\n",data.Nonce)
		fmt.Printf("Hash %x\n",string(data.Hash))
		fmt.Printf("Coinbase %s\n",string(data.Coinbase))
		fmt.Printf("Data %s\n",string(data.Data))
		fmt.Printf("IsValid %v\n",NewProofWork(data).IsValid())
		fmt.Println("\r\n")
	}
}
//block.go

package main

import "time"

//定义区块头结构体
type BlockHeader struct{
	//版本
	//区块版本号,表示本区块遵守的验证规则
	Version 			int64
	//前一区块的哈希值
	//SHA256
	PrevBlockHash		[]byte
	//梅克尔根
	//该区块中交易的梅克尔树根的哈希值 SHA256
	MerKelRoot			[]byte
	//时间戳
	//区块生成时间
	TimeStamp			int64
	//难度值
	//该区块工作量证明的难度目标
	Bits 				int64
	//随机值
	//挖矿找到的满足难度目标的随机值
	Nonce 				int64

	//*当前区块哈希值
	//实际上,区块不存储哈希值,节点接收区块后独立计算并存储在本地
	Hash 				[]byte
}

//定义区块体结构体
type Transactions struct{
	//第一条交易   矿工挖矿奖励
	Coinbase			[]byte
	//普通交易信息
	//每笔交易包括(付款方、收款方、金额、手续费等)
	Data				[]byte
}

//定义区块结构体
type Block struct{
	BlockHeader
	Transactions
}

//创建区块
func NewBlock(coinbase,data string,prevBlockHash []byte) *Block{
	var block Block
	block.Version = 1
	block.PrevBlockHash = prevBlockHash
	block.MerKelRoot = []byte{}
	block.TimeStamp = time.Now().Unix()
	block.Bits = TargetBits

	block.Coinbase = []byte(coinbase)
	block.Data = []byte(data)

	pow := NewProofWork(&block)
	nonce,hash := pow.Run()
	block.Nonce = nonce
	block.Hash = hash

	return &block
}

//创建创世块
func NewGenesisBlock() *Block{
	return NewBlock("Genesis Block","",[]byte{})
}

 

//pow.go

package main

import (
	"bytes"
	"crypto/sha256"
	"fmt"
	"math"
	"math/big"
	"time"
)

const TargetBits = 24

//定义工作量证明结构
type ProofOfWork struct{
	block *Block
	//目标值
	target *big.Int
}

//创建POW(PROOF OF WORK)的函数
func NewProofWork(block *Block) *ProofOfWork{
	//0x000000000000...01
	target := big.NewInt(1)
	//0x000000100000...00
	target.Lsh(target,256-uint(block.Bits))
	return &ProofOfWork{block,target}
}

//寻找随机数 计算哈希
func (pow *ProofOfWork)Run()(int64,[]byte){
	fmt.Println("开始挖矿...")
	fmt.Printf("target < hash: [    %x]\n",pow.target.Bytes())

	var nonce int64 = 0
	var hash [32]byte
	var hashInt big.Int
	for nonce < math.MaxInt64{
		data := pow.prepare(nonce)
		hash = sha256.Sum256(data)
		hashInt.SetBytes(hash[:])
		if hashInt.Cmp(pow.target) == -1{
			fmt.Printf("found nonce // [%x] %d\n",hash,nonce)
			break
		}else{
			nonce++
		}
	}

	//返回找到的随机数nonce和算出的哈希
	return nonce,hash[:]
}

//校验计算结果
func (pow *ProofOfWork)IsValid() bool{
	data := pow.prepare(pow.block.Nonce)
	hash := sha256.Sum256(data)
	var hashInt big.Int
	hashInt.SetBytes(hash[:])
	if hashInt.Cmp(pow.target) == -1{
		fmt.Printf("%x",hash[:])
		return true
	}else{
		return false
	}
}

func (pow *ProofOfWork)prepare(nonce int64) []byte{
	pow.block.TimeStamp = time.Now().Unix()
	block := pow.block
	tmp := [][]byte{
		Int2Bytes(block.Version),
		block.PrevBlockHash,
		block.MerKelRoot,
		Int2Bytes(block.TimeStamp),
		Int2Bytes(TargetBits),
		Int2Bytes(nonce),
		block.Coinbase,
		block.Data,
	}
	data := bytes.Join(tmp,[]byte{})
	return data
}

 

//utils.go

package main

import (
	"bytes"
	"encoding/binary"
)

func Int2Bytes(i int64) []byte{
	var buf bytes.Buffer
	err := binary.Write(&buf,binary.BigEndian,i)
	if err != nil{
		panic(-1)
	}
	return buf.Bytes()
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值