-
Notifications
You must be signed in to change notification settings - Fork 0
/
blockchain.go
72 lines (57 loc) · 1.55 KB
/
blockchain.go
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
package main
import (
"bytes"
"crypto/sha256"
"fmt"
"strconv"
"time"
)
// Blockchain is our global blockchain.
var Blockchain []Block
// Block is our basic data structure!
type Block struct {
Data string
Timestamp int64
PrevHash []byte
Hash []byte
}
// InitBlockchain creates our first Genesis node.
func InitBlockchain() {
genesisBlock := Block{"Genesis Block", time.Now().Unix(), []byte{}, []byte{}}
genesisBlock.Hash = genesisBlock.calculateHash()
Blockchain = []Block{genesisBlock}
}
// NewBlock creates a new Blockchain Block.
func NewBlock(oldBlock Block, data string) Block {
newBlock := Block{data, time.Now().Unix(), []byte{}, []byte{}}
newBlock.PrevHash = oldBlock.Hash
newBlock.Hash = newBlock.calculateHash()
return newBlock
}
// AddBlock adds a new block to the Blockchain.
func AddBlock(b Block) error {
lastestBlock := Blockchain[len(Blockchain)-1]
err := b.isValidBlock(lastestBlock)
if err != nil {
return err
}
Blockchain = append(Blockchain, b)
return nil
}
func (b *Block) calculateHash() []byte {
timestamp := []byte(strconv.FormatInt(b.Timestamp, 10))
data := []byte(b.Data)
headers := bytes.Join([][]byte{b.PrevHash, data, timestamp}, []byte{})
hash := sha256.Sum256(headers)
return hash[:]
}
func (b *Block) isValidBlock(previousBlock Block) error {
blockHash := b.calculateHash()
switch {
case !bytes.Equal(b.Hash, blockHash):
return fmt.Errorf("Invalid hash: %x %x", b.Hash, blockHash)
case !bytes.Equal(b.PrevHash, previousBlock.Hash):
return fmt.Errorf("Invalid previous hash")
}
return nil
}