区块链V3版本实现之四
部分代码(blockchain.go文件中改写addblock函数):
1 //V3版本 2 func (bc *BlockChain) AddBlock(data string) { 3 bc.db.Update(func(tx *bolt.Tx) error { 4 //所有的操作都在这里 5 6 b := tx.Bucket([]byte("blockBucket")) 7 8 if b == nil { 9 fmt.Printf("bucket不存在,请检查!\n") 10 os.Exit(1) 11 } 12 block := NewBlock(data, bc.tail) 13 b.Put(block.Hash,block.Serialize()/*将区块序列化,转成字节流*/) 14 b.Put([]byte("lastHashKey"),block.Hash) 15 16 bc.tail = block.Hash 17 18 return nil 19 }) 20 }
部分代码(blockchain.go文件中将数据修改为全局变量):
1 package main 2 3 import ( 4 "beijing_go_term2/bolt" 5 "fmt" 6 "log" 7 "os" 8 ) 9 10 //V1,V2版本 11 ////创建区块链,使用Block数组模拟 12 //type BlockChain struct { 13 // Blocks []*Block 14 //} 15 16 //V3版本 17 //使用bolt进行改写,需要2个字段 18 //1.bolt数据库的句柄 19 //2.最后一个区块的哈希值 20 type BlockChain struct { 21 //句柄 22 db *bolt.DB 23 //最后一个区块的哈希值,可以直接读取数据库,但是放在内存中更加方便 24 tail []byte 25 } 26 27 const blockChainName = "blockChain.db" 28 const blockBucketName = "blockBucket" 29 const lastHashKey = "lastHashKey" 30 31 //实现创建区块链的方法 32 func NewBlockChain() *BlockChain { 33 ////V1,V2版本使用 34 ////在创建的时候添加一个区块:创世块 35 //genesisBlock := NewBlock(genesisInfo, []byte{0x0000000000000000}) 36 // 37 //bc := BlockChain{Blocks: []*Block{genesisBlock}} 38 //return &bc 39 40 //V3版本使用 41 //功能分析 42 //1.获得数据库的句柄,打开数据库,读写数据 43 //判读是否有buket,如果没有,创建bucket 44 //写入创世块 45 //写入1astHashKey这条数据 46 //更新tai1为最后一个区块的哈希 47 //返回bc实例 48 //2.获取最后一个区块的哈希值 49 //填充给tail 50 //返回bc实例 51 52 db, err := bolt.Open(blockChainName, 0600, nil) 53 //向数据库中写入数据 54 //从数据库中读取数据 55 56 if err != nil { 57 log.Panic(err) 58 } 59 60 var tail []byte 61 62 db.Update(func(tx *bolt.Tx) error { 63 //所有的操作都在这里 64 65 b := tx.Bucket([]byte(blockBucketName)) 66 67 if b == nil { 68 //如果b为空,说明名字为"blockChain"这个桶不存在,我们需要创建之 69 fmt.Printf("bucket不存在,准备创建!\n") 70 b, err = tx.CreateBucket([]byte(blockBucketName)) 71 72 if err != nil { 73 log.Panic(err) 74 } 75 76 //添加创世块 77 genesisBlock := NewBlock(genesisInfo, []byte{}) 78 b.Put(genesisBlock.Hash,genesisBlock.Serialize()/*将区块序列化,转成字节流*/) 79 b.Put([]byte(lastHashKey),genesisBlock.Hash) 80 81 ////区块数据读取,测试写入是否成功,成功就稍后注释 82 //blockInfo := b.Get(genesisBlock.Hash) 83 //block := Deserialize(blockInfo) 84 //fmt.Printf("解码后的block数据:%v\n",block) 85 86 tail = genesisBlock.Hash 87 }else { 88 tail = b.Get([]byte(lastHashKey)) 89 } 90 91 return nil 92 }) 93 94 return &BlockChain{db,tail} 95 } 96 97 //V2版本 98 ////添加区块 99 //func (bc *BlockChain) AddBlock(data string) { 100 // 101 // //创建一个区块 102 // //bc.Block的最后一个区块的Hash值就是当前新区块的PrevBlockHash 103 // lastBlock := bc.Blocks[len(bc.Blocks) - 1] 104 // prevHash := lastBlock.Hash 105 // 106 // block := NewBlock(data, prevHash) 107 // 108 // //添加到bc.Block数组中 109 // bc.Blocks = append(bc.Blocks, block) 110 // 111 //} 112 113 //V3版本 114 func (bc *BlockChain) AddBlock(data string) { 115 bc.db.Update(func(tx *bolt.Tx) error { 116 //所有的操作都在这里 117 118 b := tx.Bucket([]byte(blockBucketName)) 119 120 if b == nil { 121 fmt.Printf("bucket不存在,请检查!\n") 122 os.Exit(1) 123 } 124 block := NewBlock(data, bc.tail) 125 b.Put(block.Hash,block.Serialize()/*将区块序列化,转成字节流*/) 126 b.Put([]byte(lastHashKey),block.Hash) 127 128 bc.tail = block.Hash 129 130 return nil 131 }) 132 }
显示效果:(删除之前的bucket后,执行2次hash)