sample_chain/proto/util/blockutils.go

179 lines
4.6 KiB
Go

package util
import (
"bytes"
"crypto/sha256"
"fmt"
"log"
pb "schain/proto"
"strings"
"github.com/pkg/errors"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/timestamppb"
)
// NewBlock 创建一个新的区块
func NewBlock(seqNum uint64, previousHash []byte) *pb.Block {
block := &pb.Block{}
block.Header = &pb.BlockHeader{}
block.Header.Number = seqNum
block.Header.Timestamp = timestamppb.Now()
block.Header.PreviousHash = previousHash
block.Header.DataHash = []byte{}
block.Data = &pb.BlockData{}
block.Metadata = &pb.BlockMetadata{}
block.Metadata.Transaction_State = []*pb.ValidationCodes{}
return block
}
func GenesisBlock() *pb.Block {
block := NewBlock(0, []byte{})
block.Header.Hash = BlockHeaderHash(block.Header)
return block
}
func CreateNewBlock(seqNum uint64, previousHash []byte, messages []*pb.Envelopes) *pb.Block {
var err error
block := NewBlock(seqNum, previousHash)
data := &pb.BlockData{
Data: make([][]byte, len(messages)),
}
for i, msg := range messages {
data.Data[i], err = proto.Marshal(msg)
if err != nil {
panic(err)
}
}
block.Data = data
block.Header.DataHash = BlockDataHash(block.Data)
block.Header.Hash = BlockHeaderHash(block.Header)
return block
}
func NewBlockSign(block *pb.Block, signatureHeader *pb.SignatureHeader, signature []byte) *pb.Block {
block.Metadata.SignatureHeader = signatureHeader
block.Metadata.Signature = signature
return block
}
// NewGenesisBlock 生成创世区块
func NewGenesisBlock() *pb.Block {
genesisBlock := NewBlock(0, []byte{})
return genesisBlock
}
func BlockBytes(b *pb.Block) []byte {
result, err := proto.Marshal(b)
if err != nil {
panic(err)
}
return result
}
// BlockHeaderBytes 获取区块头的字节数组
func BlockHeaderBytes(b *pb.BlockHeader) []byte {
result, err := proto.Marshal(b)
if err != nil {
panic(err)
}
return result
}
// BlockMetadataBytes 获取区块元数据的字节数组
func BlockMetadataBytes(b *pb.BlockMetadata) []byte {
result, err := proto.Marshal(b)
if err != nil {
panic(err)
}
return result
}
// BlockHeaderHash 计算区块头的hash
func BlockHeaderHash(b *pb.BlockHeader) []byte {
sum := sha256.Sum256(BlockHeaderBytes(b))
return sum[:]
}
// BlockDataHash 计算区块体的hash
func BlockDataHash(b *pb.BlockData) []byte {
sum := sha256.Sum256(bytes.Join(b.Data, nil))
return sum[:]
}
// GetMetadataFromBlock 从区块中获取 BlockMetadata
func GetMetadataFromBlock(block *pb.Block) (*pb.BlockMetadata, error) {
if block.Metadata == nil {
return nil, errors.New("no metadata in block")
}
return block.Metadata, nil
}
// GetMetadataFromBlockOrPanic 从区块中获取 BlockMetadata,如果出错则抛出 panic
func GetMetadataFromBlockOrPanic(block *pb.Block) *pb.BlockMetadata {
md, err := GetMetadataFromBlock(block)
if err != nil {
panic(err)
}
return md
}
func StringBlockByte(blockByte []byte) {
var lines []string
block, err := UnmarshalBlock(blockByte)
if err != nil {
log.Fatal(err)
}
lines = append(lines, fmt.Sprintf("==================================== block Number is: %d ====================================", block.Header.Number))
lines = append(lines, fmt.Sprintf("--- block PreviousHash is: %v", block.Header.PreviousHash))
lines = append(lines, fmt.Sprintf("--- block Hash is: %v", block.Header.Hash))
lines = append(lines, fmt.Sprintf("--- block DataHash is: %v", block.Header.DataHash))
lines = append(lines, fmt.Sprintf("--- block create Timestamp is: %s", block.Header.Timestamp))
for gIdx, data := range block.Data.Data {
envs, err := UnmarshalEnvelopes(data)
if err != nil {
log.Fatal(err)
}
lines = append(lines, "")
lines = append(lines, fmt.Sprintf("--- Transaction Group is: %d", gIdx))
for txIdx, envelope := range envs.Envelope {
lines = append(lines, fmt.Sprintf("======================== Transaction ID is: %s ========================", envelope.TxID))
ap, err := GetActionPayloadFromEnvelopeMsg(envelope)
if err != nil {
log.Fatal(err)
}
lines = append(lines, fmt.Sprintf("--- Transaction Input is: %v", ap.Input))
rwset, err := GetKVRWSetKwFromEnvelope(envelope)
if err != nil {
log.Fatal(err)
}
if rwset.Reads != nil {
lines = append(lines, fmt.Sprintf("--- Transaction ReadSet is: %v", rwset.Reads))
}
if rwset.Writes != nil {
lines = append(lines, fmt.Sprintf("--- Transaction WriteSet is: %v", rwset.Writes))
}
validateCode := block.Metadata.Transaction_State[gIdx].Transaction_State[txIdx]
lines = append(lines, fmt.Sprintf("--- Transaction ValidationCode is: %v", validateCode))
lines = append(lines, "")
}
}
fmt.Printf("%s\n\n\n\n\n\n", strings.Join(lines, "\n"))
}