区块链实战
字节 | 字段 | 说明 |
---|
4 | 版本 | 区块版本号,表示本区块遵守的验证规则 |
32 | 父区块头哈希值 | 前一区块的Merkle树根的哈希值,同样采取SHA256计算 |
32 | Merkle根 | 该区块中交易的Merkle树根的哈希值,同样采用SHA256计算 |
4 | 时间戳 | 该区块产生的近似时间,精确到秒的UNIX时间戳,必须严格大于前11各区块的时间的中值,同时全节点也会拒接那些超过自己两个小时的时间戳的区块 |
4 | 难度目标 | 该区块工作量证明算法的难度目标,已经使用特定算法编码 |
4 | Nonce | 未来找到满足难度目标所设定的随机数,为了解决32为随机数在算力飞升的情况下不够用的问题,规定时间戳和coinbase交易信息均改变,以此扩展nonce的位数 |
**注意:**区块不存储hash值,节点接受区块后独立计算并存储在本地。
Version 1
区块相关:
1.定义一个区块的结构Block
a.区块头:6个字段
b.区块体:字符串表示data
-
提供一个创建区块的方法
NewBlock(参数)
区块链相关
-
定义一个区块链结构BlockChain
Block数组
- 提供一个创建BlockChain()的方法
NewBlockChain()
- 提供一个添加区块的方法
AddBlock(参数)
block.go文件
package main
import (
"bytes"
"crypto/sha256"
"time"
)
type Block struct {
Version int64
PerBlockHash []byte
Hash []byte
MerKelRoot []byte
TimeStamp int64
Bits int64
Nonce int64
Data []byte
}
func NewBlock(data string ,prevBlockHash []byte) *Block {
var block Block
block = Block{
Version: 1,
PerBlockHash: prevBlockHash,
MerKelRoot: []byte{},
TimeStamp: time.Now().Unix(),
Bits: 1,
Nonce: 1,
Data: []byte(data),
}
block.SetHash()
return &block
}
func (block *Block) SetHash() {
tmp :=[][]byte{
IntToByte(block.Version),
block.PerBlockHash,
block.MerKelRoot,
IntToByte(block.TimeStamp),
IntToByte(block.Bits),
IntToByte(block.Nonce),
}
data:=bytes.Join(tmp,[]byte{})
hash := sha256.Sum256(data)
block.Hash = hash[:]
}
func NewGensisBlock() *Block{
return NewBlock("Genesis Block!",[]byte{})
}
blockChain.go文件
package main
type BlockChain struct {
blocks []*Block
}
func NewBlockChain() *BlockChain {
block := NewGensisBlock()
return &BlockChain{blocks:[]*Block{block}}
}
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 {
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)
}
}
执行结果