@ -0,0 +1,115 @@ |
|||||
|
package main |
||||
|
|
||||
|
import ( |
||||
|
"encoding/json" |
||||
|
"errors" |
||||
|
"fmt" |
||||
|
"io/ioutil" |
||||
|
"net/http" |
||||
|
"time" |
||||
|
|
||||
|
"github.com/fatih/color" |
||||
|
) |
||||
|
|
||||
|
type Block struct { |
||||
|
Hash string `json:"hash"` |
||||
|
Height int64 `json:"height"` |
||||
|
Date time.Time `json:"date"` |
||||
|
PreviousHash string `json:"previoushash"` |
||||
|
NextHash string `json:"nexthash"` |
||||
|
Data []Address `json:"data"` |
||||
|
Emitter string `json:"emitter"` //the ID of the peer that has emmited the block
|
||||
|
} |
||||
|
|
||||
|
type Blockchain struct { |
||||
|
GenesisBlock string `json:"genesisblock"` |
||||
|
LastUpdate time.Time `json:"lastupdate"` |
||||
|
Blocks []Block `json:"blocks"` |
||||
|
} |
||||
|
|
||||
|
var blockchain Blockchain |
||||
|
|
||||
|
func (bc *Blockchain) getBlockByHash(hash string) (Block, error) { |
||||
|
for _, block := range bc.Blocks { |
||||
|
if block.Hash == hash { |
||||
|
return block, nil |
||||
|
} |
||||
|
} |
||||
|
var b Block |
||||
|
return b, errors.New("Block Hash not found") |
||||
|
} |
||||
|
|
||||
|
func (bc *Blockchain) blockExists(block Block) bool { |
||||
|
for _, b := range bc.Blocks { |
||||
|
if b.Hash == block.Hash { |
||||
|
return true |
||||
|
} |
||||
|
} |
||||
|
return false |
||||
|
} |
||||
|
|
||||
|
func (bc *Blockchain) addBlock(block Block) error { |
||||
|
if blockchain.blockExists(block) { |
||||
|
return errors.New("[Error adding Block]: Block already exists in the Blockchain") |
||||
|
} |
||||
|
if len(bc.Blocks) > 0 { |
||||
|
bc.Blocks[len(bc.Blocks)-1].NextHash = block.Hash |
||||
|
} else { |
||||
|
bc.GenesisBlock = block.Hash |
||||
|
} |
||||
|
bc.Blocks = append(bc.Blocks, block) |
||||
|
|
||||
|
return nil |
||||
|
} |
||||
|
|
||||
|
func reconstructBlockchainFromBlock(urlAPI string, h string) { |
||||
|
color.Yellow("reconstructing the blockchain from last block in memory") |
||||
|
var block Block |
||||
|
var err error |
||||
|
|
||||
|
block, err = blockchain.getBlockByHash(h) |
||||
|
check(err) |
||||
|
|
||||
|
if h == "" { |
||||
|
//no genesis block yet
|
||||
|
color.Green(urlAPI + "/blocks/genesis") |
||||
|
res, err := http.Get(urlAPI + "/blocks/genesis") |
||||
|
check(err) |
||||
|
body, err := ioutil.ReadAll(res.Body) |
||||
|
check(err) |
||||
|
err = json.Unmarshal(body, &block) |
||||
|
check(err) |
||||
|
color.Yellow("[New Block]: " + block.Hash) |
||||
|
err = blockchain.addBlock(block) |
||||
|
check(err) |
||||
|
} else { |
||||
|
block.NextHash = h |
||||
|
} |
||||
|
|
||||
|
for block.NextHash != "" && block.Hash != "" { |
||||
|
res, err := http.Get(urlAPI + "/blocks/next/" + block.Hash) |
||||
|
check(err) |
||||
|
body, err := ioutil.ReadAll(res.Body) |
||||
|
check(err) |
||||
|
err = json.Unmarshal(body, &block) |
||||
|
check(err) |
||||
|
if block.Hash != "" { |
||||
|
color.Yellow("[New Block]: " + block.Hash) |
||||
|
err = blockchain.addBlock(block) |
||||
|
check(err) |
||||
|
} |
||||
|
} |
||||
|
blockchain.print() |
||||
|
} |
||||
|
|
||||
|
func (bc *Blockchain) print() { |
||||
|
color.Green("Printing Blockchain stored in memory") |
||||
|
color.Green("Genesis Block: " + bc.GenesisBlock) |
||||
|
for _, b := range bc.Blocks { |
||||
|
color.Green("Block height:") |
||||
|
fmt.Println(b.Height) |
||||
|
color.Green("Hash: " + b.Hash) |
||||
|
color.Green("Date: " + b.Date.String()) |
||||
|
color.Green("---") |
||||
|
} |
||||
|
} |