arnaucube
arnaucube/blockchainIDsystemPublic Self-hosted repository
reconstructBlockchainFromBlock, deletePeerFromPeersList when conn is closed, REST routes: GenesisBlock, NextBlock, LastBlock
arnaucode arnaucode@gmail.com
Sat, 25 Nov 2017 22:30:02 +0100
commit

d9f2bca34c6d7e8fef29d4e22698894400aeb30f

parent

c5fc0a53a7ef7b53995dd9caa7d685f89ea3e288

A blockchainIDsystem.postman_collection.json

@@ -0,0 +1,64 @@

+{ + "variables": [], + "info": { + "name": "blockchainIDsystem", + "_postman_id": "4f8e319b-3c66-8ce8-ae09-091c53a281f1", + "description": "", + "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" + }, + "item": [ + { + "name": "http://127.0.0.1:3002/register", + "request": { + "url": "http://127.0.0.1:3002/register", + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"address\": \"asdf1\"\n}" + }, + "description": "" + }, + "response": [] + }, + { + "name": "http://127.0.0.1:3002/peers", + "request": { + "url": "http://127.0.0.1:3002/peers", + "method": "GET", + "header": [], + "body": {}, + "description": "" + }, + "response": [] + }, + { + "name": "http://127.0.0.1:3002/blocks/genesis", + "request": { + "url": "http://127.0.0.1:3002/blocks/genesis", + "method": "GET", + "header": [], + "body": {}, + "description": "" + }, + "response": [] + }, + { + "name": "http://127.0.0.1:3004/blocks/next/a5B-sv24LTvo80ZvQg1uf3bmDwqyjU9LxVEtIrmkkn0=", + "request": { + "url": "http://127.0.0.1:3004/blocks/next/a5B-sv24LTvo80ZvQg1uf3bmDwqyjU9LxVEtIrmkkn0=", + "method": "GET", + "header": [], + "body": {}, + "description": "" + }, + "response": [] + } + ] +}
M peer/README.md → peer/README.md

@@ -64,8 +64,9 @@ - Adds the address (pubK of the user) to the blockchain

## TODO -- When a peer connects to the network, sends his last Block, and receives the new Blocks from this last Block -- Delete the peer from the peers list when the connection is closed +- When a peer connects to the network, sends his last Block, and receives the new Blocks from this last Block --> DONE with REST petitions, maybe is better with tcp conn +- Delete the peer from the peers list when the connection is closed --> DONE - REST: - endpoint to get if the address is in the blockchain (to verify users) - parameters Date or LastUpdate on the structs needs to be updated values +- implement rsa encryption between peers
M peer/blockchain.go → peer/blockchain.go

@@ -1,8 +1,14 @@

package main import ( + "encoding/json" "errors" + "fmt" + "io/ioutil" + "net/http" "time" + + "github.com/fatih/color" ) type Block struct {

@@ -57,7 +63,11 @@ }

} 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 {

@@ -67,3 +77,48 @@ 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 + 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 != "" { + 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) + 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("---") + } +}
M peer/config.json → peer/config.json

@@ -4,5 +4,6 @@ "port": "3001",

"restip": "127.0.0.1", "restport": "3002", "serverip": "127.0.0.1", - "serverport": "3000" + "serverport": "3000", + "serverrestport": "3002" }
M peer/connections.go → peer/connections.go

@@ -88,4 +88,7 @@ //TODO add that if the peer closed is the p2p server, show a warning message at the peer

log.Println("Peer: " + conn.RemoteAddr().String() + " connection closed") conn.Close() //TODO delete the peer from the outcomingPeersList + deletePeerFromPeersList(connPeer, &outcomingPeersList) + color.Yellow("peer deleted, current peerList:") + printPeersList() }
M peer/main.go → peer/main.go

@@ -11,11 +11,12 @@ "github.com/fatih/color"

) type Peer struct { - ID string `json:"id"` //in the future, this will be the peer hash - IP string `json:"ip"` - Port string `json:"port"` - Role string `json:"role"` //client or server - Conn net.Conn `json:"conn"` + ID string `json:"id"` //in the future, this will be the peer hash + IP string `json:"ip"` + Port string `json:"port"` + RESTPort string `json:"restport"` + Role string `json:"role"` //client or server + Conn net.Conn `json:"conn"` } var running bool

@@ -34,6 +35,7 @@

//runningPeer.ID = strconv.Itoa(randInt(1, 1000)) //0 is reserved for server runningPeer.IP = config.IP runningPeer.Port = config.Port + runningPeer.RESTPort = config.RESTPort runningPeer.ID = hashPeer(runningPeer) runningPeer.Role = "client"

@@ -66,6 +68,7 @@ serverPeer.Port = config.ServerPort

serverPeer.ID = hashPeer(serverPeer) serverPeer.Role = "server" connectToPeer(serverPeer) + reconstructBlockchainFromBlock("http://"+config.IP+":"+config.ServerRESTPort, blockchain.GenesisBlock) go acceptPeers(runningPeer) }
M peer/messages.go → peer/messages.go

@@ -44,20 +44,6 @@ //time.Sleep(1000 * time.Millisecond)

updateNetworkPeersList(peer.Conn, msg.PeersList) printPeersList() break - case "MyID": - color.Blue("MyID") - fmt.Println(msg.Content) - color.Green(peer.Conn.RemoteAddr().String()) - peer.ID = msg.Content - searchPeerAndUpdate(peer) - - //time.Sleep(1000 * time.Millisecond) - /* - updatePeersList(peer.Conn, msg.PeersList) - propagatePeersList(peer) - */ - printPeersList() - break case "Block": if !blockchain.blockExists(msg.Block) { blockchain.addBlock(msg.Block)
M peer/peers.go → peer/peers.go

@@ -35,6 +35,14 @@ }

} return r } + +func deletePeerFromPeersList(p Peer, pl *PeersList) { + i := peerIsInPeersList(p, pl.Peers) + if i != -1 { + //delete peer from pl.Peers + pl.Peers = append(pl.Peers[:i], pl.Peers[i+1:]...) + } +} func appendPeerIfNoExist(pl PeersList, p Peer) PeersList { i := peerIsInPeersList(p, pl.Peers) if i == -1 {
M peer/readConfig.go → peer/readConfig.go

@@ -7,12 +7,13 @@ )

//Config reads the config type Config struct { - IP string `json:"ip"` - Port string `json:"port"` - RestIP string `json:"restip"` - RestPort string `json:"restport"` - ServerIP string `json:"serverip"` - ServerPort string `json:"serverport"` + IP string `json:"ip"` + Port string `json:"port"` + RestIP string `json:"restip"` + RESTPort string `json:"restport"` + ServerIP string `json:"serverip"` + ServerPort string `json:"serverport"` + ServerRESTPort string `json:"serverrestport"` } var config Config
M peer/restRoutes.go → peer/restRoutes.go

@@ -6,6 +6,7 @@ "fmt"

"net/http" "github.com/fatih/color" + "github.com/gorilla/mux" ) type Routes []Route

@@ -29,6 +30,24 @@ "POST",

"/register", PostUser, }, + Route{ + "GenesisBlock", + "GET", + "/blocks/genesis", + GenesisBlock, + }, + Route{ + "NextBlock", + "GET", + "/blocks/next/{blockhash}", + NextBlock, + }, + Route{ + "LastBlock", + "GET", + "/blocks/last", + LastBlock, + }, } type Address struct {

@@ -65,3 +84,39 @@ jResp, err := json.Marshal(blockchain)

check(err) fmt.Fprintln(w, string(jResp)) } + +func GenesisBlock(w http.ResponseWriter, r *http.Request) { + var genesis Block + if len(blockchain.Blocks) >= 0 { + genesis = blockchain.Blocks[0] + } + + jResp, err := json.Marshal(genesis) + check(err) + fmt.Fprintln(w, string(jResp)) +} + +func NextBlock(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + blockhash := vars["blockhash"] + + currBlock, err := blockchain.getBlockByHash(blockhash) + check(err) + nextBlock, err := blockchain.getBlockByHash(currBlock.NextHash) + check(err) + + jResp, err := json.Marshal(nextBlock) + check(err) + fmt.Fprintln(w, string(jResp)) +} + +func LastBlock(w http.ResponseWriter, r *http.Request) { + var genesis Block + if len(blockchain.Blocks) > 0 { + genesis = blockchain.Blocks[len(blockchain.Blocks)-1] + } + + jResp, err := json.Marshal(genesis) + check(err) + fmt.Fprintln(w, string(jResp)) +}
M peer/restServer.go → peer/restServer.go

@@ -11,10 +11,10 @@ func runRestServer() {

//run API log.Println("server running") log.Print("port: ") - log.Println(config.RestPort) + log.Println(config.RESTPort) router := NewRouter() headersOk := handlers.AllowedHeaders([]string{"X-Requested-With", "Access-Control-Allow-Origin"}) originsOk := handlers.AllowedOrigins([]string{"*"}) methodsOk := handlers.AllowedMethods([]string{"GET", "HEAD", "POST", "PUT", "OPTIONS"}) - log.Fatal(http.ListenAndServe(":"+config.RestPort, handlers.CORS(originsOk, headersOk, methodsOk)(router))) + log.Fatal(http.ListenAndServe(":"+config.RESTPort, handlers.CORS(originsOk, headersOk, methodsOk)(router))) }