blockchainIDsystem/peer/blockchain.go
peer/blockchain.goRaw
1package main
2
3import (
4 "encoding/json"
5 "errors"
6 "fmt"
7 "io/ioutil"
8 "net/http"
9 "time"
10
11 "github.com/fatih/color"
12)
13
14type Block struct {
15 Hash string `json:"hash"`
16 Height int64 `json:"height"`
17 Date time.Time `json:"date"`
18 PreviousHash string `json:"previoushash"`
19 NextHash string `json:"nexthash"`
20 Data []Address `json:"data"`
21 Emitter string `json:"emitter"` //the ID of the peer that has emmited the block
22}
23
24type Blockchain struct {
25 GenesisBlock string `json:"genesisblock"`
26 LastUpdate time.Time `json:"lastupdate"`
27 Blocks []Block `json:"blocks"`
28}
29
30var blockchain Blockchain
31
32func (bc *Blockchain) getBlockByHash(hash string) (Block, error) {
33 for _, block := range bc.Blocks {
34 if block.Hash == hash {
35 return block, nil
36 }
37 }
38 var b Block
39 return b, errors.New("Block Hash not found")
40}
41
42func (bc *Blockchain) createBlock(address Address) Block {
43 var b Block
44 b.Height = int64(len(bc.Blocks))
45 if len(bc.Blocks) == 0 {
46 b.Height = 0
47 } else {
48 b.PreviousHash = bc.Blocks[len(bc.Blocks)-1].Hash
49 }
50 b.Date = time.Now()
51 b.Data = append(b.Data, address)
52 b.Emitter = runningPeer.ID
53
54 b.Hash = hashBlock(b)
55 return b
56}
57
58func (bc *Blockchain) blockExists(block Block) bool {
59 for _, b := range bc.Blocks {
60 if b.Hash == block.Hash {
61 return true
62 }
63 }
64 return false
65}
66
67func (bc *Blockchain) addBlock(block Block) error {
68 if blockchain.blockExists(block) {
69 return errors.New("[Error adding Block]: Block already exists in the Blockchain")
70 }
71 if len(bc.Blocks) > 0 {
72 bc.Blocks[len(bc.Blocks)-1].NextHash = block.Hash
73 } else {
74 bc.GenesisBlock = block.Hash
75 }
76 bc.Blocks = append(bc.Blocks, block)
77
78 return nil
79}
80
81func reconstructBlockchainFromBlock(urlAPI string, h string) {
82 color.Yellow("reconstructing the blockchain from last block in memory")
83 var block Block
84 if h == "" {
85 //no genesis block yet
86 color.Green(urlAPI + "/blocks/genesis")
87 res, err := http.Get(urlAPI + "/blocks/genesis")
88 check(err)
89 body, err := ioutil.ReadAll(res.Body)
90 check(err)
91 err = json.Unmarshal(body, &block)
92 check(err)
93 color.Yellow("[New Block]: " + block.Hash)
94 err = blockchain.addBlock(block)
95 check(err)
96 } else {
97 block.NextHash = h
98 }
99
100 for block.NextHash != "" {
101 res, err := http.Get(urlAPI + "/blocks/next/" + block.Hash)
102 check(err)
103 body, err := ioutil.ReadAll(res.Body)
104 check(err)
105 err = json.Unmarshal(body, &block)
106 check(err)
107 color.Yellow("[New Block]: " + block.Hash)
108 err = blockchain.addBlock(block)
109 check(err)
110 }
111 blockchain.print()
112}
113
114func (bc *Blockchain) print() {
115 color.Green("Printing Blockchain stored in memory")
116 color.Green("Genesis Block: " + bc.GenesisBlock)
117 for _, b := range bc.Blocks {
118 color.Green("Block height:")
119 fmt.Println(b.Height)
120 color.Green("Hash: " + b.Hash)
121 color.Green("Date: " + b.Date.String())
122 color.Green("---")
123 }
124}