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 var err error
85
86 block, err = blockchain.getBlockByHash(h)
87 check(err)
88
89 if h == "" {
90 //no genesis block yet
91 color.Green(urlAPI + "/blocks/genesis")
92 res, err := http.Get(urlAPI + "/blocks/genesis")
93 check(err)
94 body, err := ioutil.ReadAll(res.Body)
95 check(err)
96 err = json.Unmarshal(body, &block)
97 check(err)
98 color.Yellow("[New Block]: " + block.Hash)
99 err = blockchain.addBlock(block)
100 check(err)
101 } else {
102 block.NextHash = h
103 }
104
105 for block.NextHash != "" && block.Hash != "" {
106 res, err := http.Get(urlAPI + "/blocks/next/" + block.Hash)
107 check(err)
108 body, err := ioutil.ReadAll(res.Body)
109 check(err)
110 err = json.Unmarshal(body, &block)
111 check(err)
112 if block.Hash != "" {
113 color.Yellow("[New Block]: " + block.Hash)
114 err = blockchain.addBlock(block)
115 check(err)
116 }
117 }
118 blockchain.print()
119}
120
121func (bc *Blockchain) print() {
122 color.Green("Printing Blockchain stored in memory")
123 color.Green("Genesis Block: " + bc.GenesisBlock)
124 for _, b := range bc.Blocks {
125 color.Green("Block height:")
126 fmt.Println(b.Height)
127 color.Green("Hash: " + b.Hash)
128 color.Green("Date: " + b.Date.String())
129 color.Green("---")
130 }
131}