diff --git a/blockchainIDsystem.postman_collection.json b/blockchainIDsystem.postman_collection.json new file mode 100644 index 0000000..3d2f271 --- /dev/null +++ b/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": [] + } + ] +} \ No newline at end of file diff --git a/peer/README.md b/peer/README.md index 678cc06..67eba0c 100644 --- a/peer/README.md +++ b/peer/README.md @@ -64,8 +64,9 @@ Needs the config.json file: ## 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 diff --git a/peer/blockchain.go b/peer/blockchain.go index 154d098..7d2d2b2 100644 --- a/peer/blockchain.go +++ b/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 @@ func (bc *Blockchain) blockExists(block Block) bool { } 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 @@ func (bc *Blockchain) addBlock(block Block) error { 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("---") + } +} diff --git a/peer/config.json b/peer/config.json index da24af1..a155e62 100755 --- a/peer/config.json +++ b/peer/config.json @@ -4,5 +4,6 @@ "restip": "127.0.0.1", "restport": "3002", "serverip": "127.0.0.1", - "serverport": "3000" + "serverport": "3000", + "serverrestport": "3002" } diff --git a/peer/connections.go b/peer/connections.go index 8aeb805..4e9ce50 100644 --- a/peer/connections.go +++ b/peer/connections.go @@ -88,4 +88,7 @@ func handleConn(conn net.Conn, connPeer 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() } diff --git a/peer/main.go b/peer/main.go index 9cd38a3..4532420 100644 --- a/peer/main.go +++ b/peer/main.go @@ -11,11 +11,12 @@ import ( ) 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 @@ func main() { //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 @@ func main() { serverPeer.ID = hashPeer(serverPeer) serverPeer.Role = "server" connectToPeer(serverPeer) + reconstructBlockchainFromBlock("http://"+config.IP+":"+config.ServerRESTPort, blockchain.GenesisBlock) go acceptPeers(runningPeer) } diff --git a/peer/messages.go b/peer/messages.go index f7ed337..d41b59c 100644 --- a/peer/messages.go +++ b/peer/messages.go @@ -44,20 +44,6 @@ func messageHandler(peer Peer, msg Msg) { 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) diff --git a/peer/peer b/peer/peer index a5d02ee..93ce71f 100755 Binary files a/peer/peer and b/peer/peer differ diff --git a/peer/peers.go b/peer/peers.go index 82d0abd..d402d9c 100644 --- a/peer/peers.go +++ b/peer/peers.go @@ -35,6 +35,14 @@ func peerIsInPeersList(p Peer, pl []Peer) int { } 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 { diff --git a/peer/readConfig.go b/peer/readConfig.go index aeec87a..a148c5b 100755 --- a/peer/readConfig.go +++ b/peer/readConfig.go @@ -7,12 +7,13 @@ import ( //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 diff --git a/peer/restRoutes.go b/peer/restRoutes.go index a01682b..b2f6690 100755 --- a/peer/restRoutes.go +++ b/peer/restRoutes.go @@ -6,6 +6,7 @@ import ( "net/http" "github.com/fatih/color" + "github.com/gorilla/mux" ) type Routes []Route @@ -29,6 +30,24 @@ var routes = Routes{ "/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 @@ func PostUser(w http.ResponseWriter, r *http.Request) { 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)) +} diff --git a/peer/restServer.go b/peer/restServer.go index dc171b6..9d7e66b 100644 --- a/peer/restServer.go +++ b/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))) }