创建区块链之v2实现pow(ProofOfWork工作量证明)
2018-10-25 00:30
771 查看
block.go
package main import ( "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 main import "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 main import ( "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 main import ( "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 main import "fmt" func main(){ bc := NewBlockChain() bc.AddBlock("班长转给老师一枚比特币") bc.AddBlock("班长又转给老师一枚比特币") for i, block := range bc.blocks 5b4 { 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 : 010000000000000000000000000000000000000000000000000000000000 Found Hash:00000014312c76058b55905dbf9915019c484df5f64b9655d01985e050e16edd Begin Minng ... target hash : 010000000000000000000000000000000000000000000000000000000000 Found Hash:000000d3c28e9cff07f43949c6c6f23444c1beb7494aebb3be5cf74614e77f04 Begin Minng ... target hash : 010000000000000000000000000000000000000000000000000000000000 Found Hash:0000004b9205eab846bcf921c952ea2a91e103a4c37170304c4e1bb85d32d73e ====block num: 0 Data:Genesis Block! Version: 1 PrevHash: Hash:5bd09d11 TimeStamp:1540398353 MerKel: Nonce:26865217 IsvALID:true ====block num: 1 Data:班长转给老师一枚比特币 Version: 1 PrevHash:00000014312c76058b55905dbf9915019c484df5f64b9655d01985e050e16edd Hash:5bd09d35 TimeStamp:1540398389 MerKel: Nonce:6908425 IsvALID:true ====block num: 2 Data:班长又转给老师一枚比 2230 特币 Version: 1 PrevHash:000000d3c28e9cff07f43949c6c6f23444c1beb7494aebb3be5cf74614e77f04 Hash:5bd09d42 TimeStamp:1540398402 MerKel: Nonce:70302967 IsvALID:true
相关文章推荐
- 区块链初始化与实现POW工作量证明
- 兄弟连区块链入门教程分享区块链POW证明代码实现demo
- 给自己的区块链添加POW-工作量证明
- 任何国家都无法限制数字货币。为什么呢? 要想明白这个问题需要具备一点区块链的基础知识: 区块链使用的大致技术包括以下几种: a.点对点网络设计 b.加密技术应用 c.分布式算法的实现 d.数据存储技术 e.拜占庭算法 f.权益证明POW,POS,DPOS 原因一: 点对点网络设计 其中点对点的P2P网络是bittorent ,由于是点对点的网络,没有中心化,因此在全球分布式的网
- 任何国家都无法限制数字货币。为什么呢? 要想明白这个问题需要具备一点区块链的基础知识: 区块链使用的大致技术包括以下几种: a.点对点网络设计 b.加密技术应用 c.分布式算法的实现 d.数据存储技术 e.拜占庭算法 f.权益证明POW,POS,DPOS 原因一: 点对点网络设计 其中点对点的P2P网络是bittorent ,由于是点对点的网络,没有中心化,因此在全球分布式的网
- 区块链简史(二):一篇文章看懂比特币工作量证明和矿工存在意义
- 区块链的共识机制之工作量证明机制
- GO语言实现区块链Part2 Proof-of-Work
- Proof of work - 工作量证明
- 用python阐释工作量证明(proof of work)
- [译]用go进行区块链开发2:工作量证明
- 区块链在中国(4):比特币的工作量证明
- 创建区块链实现之v3本地持久化(bolt数据库的序列化和反序列化)和命令行参数
- 揭秘比特币和区块链(二):什么是工作量证明?
- 基于Java语言构建区块链(二)—— 工作量证明
- Proof of work - 工作量证明
- DPOS委托权益证明 vs POW工作量证明
- 揭秘比特币和区块链(二):什么是工作量证明?
- 学习区块链的基础知识--工作量证明
- Python实现类似比特币的加密货币区块链的创建与交易实例