diff options
Diffstat (limited to 'pkg/block/block.go')
-rw-r--r-- | pkg/block/block.go | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/pkg/block/block.go b/pkg/block/block.go new file mode 100644 index 0000000..843f43f --- /dev/null +++ b/pkg/block/block.go @@ -0,0 +1,90 @@ +package block + +import ( + "Chain/pkg/pro" + "crypto/sha256" + "fmt" + "google.golang.org/protobuf/proto" +) + +// Header provides information about the Block. +// Version is the Block's version. +// PreviousHash is the hash of the previous Block. +// MerkleRoot is the hash of all the Block's Transactions. +// DifficultyTarget is the difficulty of achieving a winning Nonce. +// Nonce is a "number only used once" that satisfies the DifficultyTarget. +// Timestamp is when the Block was successfully mined. +type Header struct { + Version uint32 + PreviousHash string + MerkleRoot string + DifficultyTarget string + Nonce uint32 + Timestamp uint32 +} + +// Block includes a Header and a slice of Transactions. +type Block struct { + Header *Header + Transactions []*Transaction +} + +// EncodeHeader returns a pro.Header given a Header. +func EncodeHeader(header *Header) *pro.Header { + return &pro.Header{ + Version: header.Version, + PreviousHash: header.PreviousHash, + MerkleRoot: header.MerkleRoot, + DifficultyTarget: header.DifficultyTarget, + Nonce: header.Nonce, + Timestamp: header.Timestamp, + } +} + +// DecodeHeader returns a Header given a pro.Header. +func DecodeHeader(pheader *pro.Header) *Header { + return &Header{ + Version: pheader.GetVersion(), + PreviousHash: pheader.GetPreviousHash(), + MerkleRoot: pheader.GetMerkleRoot(), + DifficultyTarget: pheader.GetDifficultyTarget(), + Nonce: pheader.GetNonce(), + Timestamp: pheader.GetTimestamp(), + } +} + +// EncodeBlock returns a pro.Block given a Block. +func EncodeBlock(b *Block) *pro.Block { + var ptxs []*pro.Transaction + for _, tx := range b.Transactions { + ptxs = append(ptxs, EncodeTransaction(tx)) + } + return &pro.Block{ + Header: EncodeHeader(b.Header), + Transactions: ptxs, + } +} + +// DecodeBlock returns a Block given a pro.Block. +func DecodeBlock(pb *pro.Block) *Block { + var txs []*Transaction + for _, ptx := range pb.GetTransactions() { + txs = append(txs, DecodeTransaction(ptx)) + } + return &Block{ + Header: DecodeHeader(pb.GetHeader()), + Transactions: txs, + } +} + +// Hash returns the hash of the block (which is done via the header) +func (block *Block) Hash() string { + h := sha256.New() + pb := EncodeHeader(block.Header) + bytes, err := proto.Marshal(pb) + if err != nil { + fmt.Errorf("[block.Hash()] Unable to marshal block") + } + h.Write(bytes) + return fmt.Sprintf("%x", h.Sum(nil)) +} |