代码链接
设置Block结构体
为什么“时间戳”英文是敏感词,佛了!
type Block struct {
// 1. Block height
Height int64
// 2. HASH of the previous block
PrevBlockHash []byte
// 3. Transaction data
Data []byte
// 4. Current time
时间戳 int64
// 5. Hash
Hash []byte
}
为指定Block设置hash
func (block *Block) SetHash() {
// 1. Convert block height to byte slice
heightBytes := Int64ToHex(block.Timestamp)
// 2. Convert timestamp to byte slices
timeString := strconv.FormatInt(block.Timestamp, 2)
timeBytes := []byte(timeString)
// 3. Stitch all attributes
blockBytes := bytes.Join([][]byte{heightBytes, block.PrevBlockHash, block.Data, timeBytes, block.Hash}, []byte{})
// 4. Generate a hash of the current block
byteArray := sha256.Sum256(blockBytes)
block.Hash = byteArray[:]
}
将时间戳int64转换为[]byte的工具函数为:
func Int64ToHex(data int64) (byteSlice []byte) {
w := new(bytes.Buffer)
err := binary.Write(w, binary.BigEndian, data)
if err != nil {
log.Panic(err)
}
byteSlice = w.Bytes()
return
}
使用工厂模式返回一个新的Block
func NewBlock(data string, height int64, preBlockHash []byte) (block *Block) {
block = &Block{
Height:height,
PrevBlockHash:preBlockHash,
Data:[]byte(data),
Timestamp:time.Now().Unix(),
}
block.SetHash()
return
}
主函数
在程序入口用工厂函数生成一个区块,并打印:
func main() {
block := BLC.NewBlock("TiN Block", 1, make([]byte, 32))
fmt.Printf("block: %#v\n", block)
}
标准输出:
block: &BLC.Block{Height:1, PrevBlockHash:[]uint8{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, Data:[]uint8{0x54, 0x69, 0x4e, 0x20, 0x42, 0x6c, 0x6f, 0x63, 0x6b}, Timestamp:1582548920, Hash:[]uint8{0xc4, 0xab, 0x5f, 0x9c, 0x40, 0xcb, 0x7f, 0xc5, 0xd7, 0xa3, 0xe0, 0x85, 0xb5, 0x68, 0x46, 0xdd, 0xc2, 0xed, 0x44, 0xcb, 0x8b, 0x9f, 0x4, 0x43, 0x2a, 0x33, 0xd, 0xd5, 0x44, 0x80, 0xf7, 0xfd}}
由此我们生成了第一个区块,它包含5部分数据:
- 当前该区块的高度,为1;
- 上一个区块的hash,系长度为32,数据全为0的字节切片;
- 当前该区块所包含的数据,可以理解为交易数据;
- 当前该区块生成时间的时间戳;
- 当前该区块的hash,系长度为32,内容由当前区块前4部分的值通过sha256函数生成的字节切片。