mirror of
https://github.com/arnaucube/blockchainIDsystem.git
synced 2026-02-07 02:56:43 +01:00
implemented the blockchain, implemented the blocks propagation throught peers, implemented REST GetPeers and PostUser (address, pubK). Everything without any kind of blockchain verification. No cryptography yet.
This commit is contained in:
@@ -19,3 +19,53 @@ Needs the config.json file:
|
||||
"serverport": "3000"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Peer REST API
|
||||
- GET /
|
||||
- Returns the peer.ID (where peer.ID = hash(peer.IP + ":" + peer.Port))
|
||||
|
||||
|
||||
- GET /peers
|
||||
- Returns the peer outcomingPeersList (the peers which the peer have connection)
|
||||
|
||||
```json
|
||||
{
|
||||
"PeerID": "VOnL-15rFsUiCnRoyGFksKvWKcwNBRz5iarRem0Ilvo=",
|
||||
"peerslist": [
|
||||
{
|
||||
"id": "VOnL-15rFsUiCnRoyGFksKvWKcwNBRz5iarRem0Ilvo=",
|
||||
"ip": "127.0.0.1",
|
||||
"port": "3000",
|
||||
"role": "server",
|
||||
"conn": null
|
||||
},
|
||||
{
|
||||
"id": "Lk9jEP1YcOAzl51yY61GdWADNe35_g5Teh12JeguHhA=",
|
||||
"ip": "127.0.0.1",
|
||||
"port": "3003",
|
||||
"role": "client",
|
||||
"conn": {}
|
||||
},
|
||||
{
|
||||
"id": "xj78wuyN2_thFBsXOUXnwij4L8vualxQ9GnVRK6RS4c=",
|
||||
"ip": "127.0.0.1",
|
||||
"port": "3005",
|
||||
"role": "client",
|
||||
"conn": {}
|
||||
}
|
||||
],
|
||||
"date": "0001-01-01T00:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
- POST /register
|
||||
- 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
|
||||
- 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
|
||||
|
||||
69
peer/blockchain.go
Normal file
69
peer/blockchain.go
Normal file
@@ -0,0 +1,69 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
)
|
||||
|
||||
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) createBlock(address Address) Block {
|
||||
var b Block
|
||||
b.Height = int64(len(bc.Blocks))
|
||||
if len(bc.Blocks) == 0 {
|
||||
b.Height = 0
|
||||
} else {
|
||||
b.PreviousHash = bc.Blocks[len(bc.Blocks)-1].Hash
|
||||
}
|
||||
b.Date = time.Now()
|
||||
b.Data = append(b.Data, address)
|
||||
b.Emitter = runningPeer.ID
|
||||
|
||||
b.Hash = hashBlock(b)
|
||||
return b
|
||||
}
|
||||
|
||||
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 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
|
||||
}
|
||||
@@ -57,7 +57,8 @@ func handleConn(conn net.Conn, connPeer Peer) {
|
||||
log.Println("handling conn: " + conn.RemoteAddr().String())
|
||||
//reply to the conn, send the peerList
|
||||
var msg Msg
|
||||
msg = msg.construct("PeersList", "here my outcomingPeersList", outcomingPeersList)
|
||||
msg.construct("PeersList", "here my outcomingPeersList")
|
||||
msg.PeersList = outcomingPeersList
|
||||
msgB := msg.toBytes()
|
||||
_, err := conn.Write(msgB)
|
||||
check(err)
|
||||
|
||||
20
peer/main.go
20
peer/main.go
@@ -5,7 +5,6 @@ import (
|
||||
"math/rand"
|
||||
"net"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/fatih/color"
|
||||
@@ -32,9 +31,10 @@ func main() {
|
||||
//read configuration file
|
||||
readConfig("config.json")
|
||||
|
||||
runningPeer.ID = strconv.Itoa(randInt(1, 1000)) //0 is reserved for server
|
||||
//runningPeer.ID = strconv.Itoa(randInt(1, 1000)) //0 is reserved for server
|
||||
runningPeer.IP = config.IP
|
||||
runningPeer.Port = config.Port
|
||||
runningPeer.ID = hashPeer(runningPeer)
|
||||
runningPeer.Role = "client"
|
||||
|
||||
go runRestServer()
|
||||
@@ -45,7 +45,8 @@ func main() {
|
||||
color.Yellow("Running as p2p server")
|
||||
runningPeer.Role = "server"
|
||||
runningPeer.Port = config.ServerPort
|
||||
runningPeer.ID = "0"
|
||||
runningPeer.ID = hashPeer(runningPeer)
|
||||
//runningPeer.ID = "0"
|
||||
}
|
||||
}
|
||||
thisPeerID = runningPeer.ID
|
||||
@@ -58,12 +59,13 @@ func main() {
|
||||
go acceptPeers(runningPeer)
|
||||
}
|
||||
if runningPeer.Role == "client" {
|
||||
var newPeer Peer
|
||||
newPeer.ID = "0"
|
||||
newPeer.IP = config.ServerIP
|
||||
newPeer.Port = config.ServerPort
|
||||
newPeer.Role = "server"
|
||||
connectToPeer(newPeer)
|
||||
var serverPeer Peer
|
||||
//serverPeer.ID = "0"
|
||||
serverPeer.IP = config.ServerIP
|
||||
serverPeer.Port = config.ServerPort
|
||||
serverPeer.ID = hashPeer(serverPeer)
|
||||
serverPeer.Role = "server"
|
||||
connectToPeer(serverPeer)
|
||||
go acceptPeers(runningPeer)
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ type Msg struct {
|
||||
Date time.Time `json:"date"`
|
||||
Content string `json:"content"`
|
||||
PeersList PeersList `json:"peerslist"`
|
||||
Block Block `json:"block"`
|
||||
}
|
||||
|
||||
func messageHandler(peer Peer, msg Msg) {
|
||||
@@ -57,18 +58,22 @@ func messageHandler(peer Peer, msg Msg) {
|
||||
*/
|
||||
printPeersList()
|
||||
break
|
||||
case "Block":
|
||||
if !blockchain.blockExists(msg.Block) {
|
||||
blockchain.addBlock(msg.Block)
|
||||
propagateBlock(msg.Block)
|
||||
}
|
||||
break
|
||||
default:
|
||||
log.Println("Msg.Type not supported")
|
||||
break
|
||||
}
|
||||
|
||||
}
|
||||
func (msg Msg) construct(msgtype string, msgcontent string, peersList PeersList) Msg {
|
||||
func (msg *Msg) construct(msgtype string, msgcontent string) {
|
||||
msg.Type = msgtype
|
||||
msg.Content = msgcontent
|
||||
msg.PeersList = peersList
|
||||
msg.Date = time.Now()
|
||||
return msg
|
||||
}
|
||||
func (msg Msg) toBytes() []byte {
|
||||
msgS, err := json.Marshal(msg)
|
||||
|
||||
@@ -74,22 +74,16 @@ func propagatePeersList(p Peer) {
|
||||
if peer.ID != p.ID && p.ID != "" {
|
||||
color.Yellow(peer.ID + " - " + p.ID)
|
||||
var msg Msg
|
||||
msg = msg.construct("PeersList", "here my outcomingPeersList", outcomingPeersList)
|
||||
msg.construct("PeersList", "here my outcomingPeersList")
|
||||
msg.PeersList = outcomingPeersList
|
||||
msgB := msg.toBytes()
|
||||
_, err := peer.Conn.Write(msgB)
|
||||
check(err)
|
||||
} else {
|
||||
//to the peer that has sent the peerList, we send our ID
|
||||
/*
|
||||
var msg Msg
|
||||
var pl PeersList
|
||||
msg = msg.construct("MyID", runningPeer.ID, pl)
|
||||
msgB := msg.toBytes()
|
||||
_, err := p.Conn.Write(msgB)
|
||||
check(err)
|
||||
*/
|
||||
//to the peer that has sent the peerList, we send our PeersList
|
||||
var msg Msg
|
||||
msg = msg.construct("PeersList_Response", "here my outcomingPeersList", outcomingPeersList)
|
||||
msg.construct("PeersList_Response", "here my outcomingPeersList")
|
||||
msg.PeersList = outcomingPeersList
|
||||
msgB := msg.toBytes()
|
||||
_, err := peer.Conn.Write(msgB)
|
||||
check(err)
|
||||
@@ -123,3 +117,18 @@ func printPeersList() {
|
||||
}
|
||||
fmt.Println("")
|
||||
}
|
||||
|
||||
//send the block to all the peers of the outcomingPeersList
|
||||
func propagateBlock(b Block) {
|
||||
//prepare the msg to send to all connected peers
|
||||
var msg Msg
|
||||
msg.construct("Block", "new block")
|
||||
msg.Block = b
|
||||
msgB := msg.toBytes()
|
||||
for _, peer := range outcomingPeersList.Peers {
|
||||
if peer.Conn != nil {
|
||||
_, err := peer.Conn.Write(msgB)
|
||||
check(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
67
peer/restRoutes.go
Executable file
67
peer/restRoutes.go
Executable file
@@ -0,0 +1,67 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/fatih/color"
|
||||
)
|
||||
|
||||
type Routes []Route
|
||||
|
||||
var routes = Routes{
|
||||
Route{
|
||||
"Index",
|
||||
"GET",
|
||||
"/",
|
||||
Index,
|
||||
},
|
||||
Route{
|
||||
"GetPeers",
|
||||
"GET",
|
||||
"/peers",
|
||||
GetPeers,
|
||||
},
|
||||
Route{
|
||||
"PostUser",
|
||||
"POST",
|
||||
"/register",
|
||||
PostUser,
|
||||
},
|
||||
}
|
||||
|
||||
type Address struct {
|
||||
Address string `json:"address"` //the pubK of the user, to perform logins
|
||||
}
|
||||
|
||||
func Index(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintln(w, runningPeer.ID)
|
||||
}
|
||||
func GetPeers(w http.ResponseWriter, r *http.Request) {
|
||||
jResp, err := json.Marshal(outcomingPeersList)
|
||||
check(err)
|
||||
fmt.Fprintln(w, string(jResp))
|
||||
}
|
||||
func PostUser(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
decoder := json.NewDecoder(r.Body)
|
||||
var address Address
|
||||
err := decoder.Decode(&address)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer r.Body.Close()
|
||||
fmt.Println(address)
|
||||
color.Blue(address.Address)
|
||||
|
||||
//TODO add the verification of the address, to decide if it's accepted to create a new Block
|
||||
block := blockchain.createBlock(address)
|
||||
blockchain.addBlock(block)
|
||||
|
||||
go propagateBlock(block)
|
||||
|
||||
jResp, err := json.Marshal(blockchain)
|
||||
check(err)
|
||||
fmt.Fprintln(w, string(jResp))
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type Routes []Route
|
||||
|
||||
var routes = Routes{
|
||||
Route{
|
||||
"Index",
|
||||
"GET",
|
||||
"/",
|
||||
Index,
|
||||
},
|
||||
}
|
||||
|
||||
func Index(w http.ResponseWriter, r *http.Request) {
|
||||
//ipFilter(w, r)
|
||||
fmt.Fprintln(w, runningPeer.ID)
|
||||
}
|
||||
1
peer/tests.sh
Normal file
1
peer/tests.sh
Normal file
@@ -0,0 +1 @@
|
||||
curl -X POST -F address="thisisasampleaddress" http://127.0.0.1:3002/register
|
||||
@@ -1,6 +1,9 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"math/rand"
|
||||
"net"
|
||||
"strings"
|
||||
@@ -27,3 +30,22 @@ func randInt(min int, max int) int {
|
||||
r := rand.Intn(max-min) + min
|
||||
return r
|
||||
}
|
||||
func hashPeer(p Peer) string {
|
||||
/*peerJson, err := json.Marshal(p)
|
||||
check(err)
|
||||
peerString := string(peerJson)*/
|
||||
peerString := p.IP + ":" + p.Port
|
||||
|
||||
h := sha256.New()
|
||||
h.Write([]byte(peerString))
|
||||
return base64.URLEncoding.EncodeToString(h.Sum(nil))
|
||||
}
|
||||
func hashBlock(b Block) string {
|
||||
blockJson, err := json.Marshal(b)
|
||||
check(err)
|
||||
blockString := string(blockJson)
|
||||
|
||||
h := sha256.New()
|
||||
h.Write([]byte(blockString))
|
||||
return base64.URLEncoding.EncodeToString(h.Sum(nil))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user