arnaucube
arnaucube/blockchainIDsystemPublic Self-hosted repository
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}