aboutsummaryrefslogtreecommitdiff
path: root/pkg/block/block.go
blob: 843f43fc45b031d3989d1bd7201876a133bfda34 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
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))
}