|
|
@ -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("---") |
|
|
|
} |
|
|
|
} |