Skip to content
Snippets Groups Projects
Commit b37cd29c authored by xavier.perret's avatar xavier.perret
Browse files

Merge branch 'vite' into 'master'

Vite

See merge request !1
parents d8325e09 e5f0f5c8
Branches
No related tags found
1 merge request!1Vite
...@@ -4,6 +4,10 @@ ...@@ -4,6 +4,10 @@
### Developing and deploying a broadcast algorithm for a blockchain management system on a Cloud infrastructure ### Developing and deploying a broadcast algorithm for a blockchain management system on a Cloud infrastructure
- Student : Xavier Perret
- <ssh://git@ssh.hesge.ch:10572/xavier.perret/perso-distributed-systems.git>
- <https://gitedu.hesge.ch/xavier.perret/perso-distributed-systems.git>
### Client ### Client
To launch the client you need to run the following command: To launch the client you need to run the following command:
...@@ -17,8 +21,23 @@ it to neighbours instead on manually entering an ip. ...@@ -17,8 +21,23 @@ it to neighbours instead on manually entering an ip.
### Server ### Server
To launch the server you need to run the following command: #### Root Server
To lauch the server to which you wish to send commands using the client you need to do
```bash
go main.go --config=neighbor-0.yaml --server --root
```
#### Normal Server
To launch the other server you need to run the following command:
```bash ```bash
go main.go --config=server_config.yaml --server go main.go --config=server_config.yaml --server
``` ```
### Functionalities
- Able to create a transaction from the client and then request to root server to broadcast by wave to all the other servers
- Able to send a rate request from client to root server then broadcast by wave to all the other servers (buggy at the moment)
- Not able to fake a transaction yet
- Able to print all local transaction from any server or client
\ No newline at end of file
...@@ -77,86 +77,119 @@ func isTransactionValid(trans Transaction) bool { ...@@ -77,86 +77,119 @@ func isTransactionValid(trans Transaction) bool {
// is the same as the ones stored in the other nodes. The result (rate) is a percentage representing the // is the same as the ones stored in the other nodes. The result (rate) is a percentage representing the
// transactions which are the same as the one stored locally. This function relies on the broadcast by wave // transactions which are the same as the one stored locally. This function relies on the broadcast by wave
// with ACK distributed algorithm. However, some adjustments are needed to implement this function. // with ACK distributed algorithm. However, some adjustments are needed to implement this function.
func vote(trans Transaction) AckTransaction { func vote(server net.Listener, trans Transaction, config Config, parentAddress string, stimulatedByClient bool) AckTransaction {
var ack AckTransaction var ack AckTransaction
ack.Id = ""
ack.TotalNodes = 0
ack.AmountOfCorrectNode = 0
/* var transactionToRate Transaction
var err error
var reach bool = false
var count uint32 = 0
var idParent uint8 = 0
var isTransmitterAServer bool = infosNode.Is_a_server_address(addrTransmitter) for _, transactionInDatabase := range DB {
if transactionInDatabase.Id == trans.Id {
ack.Id = trans.Id
transactionToRate = transactionInDatabase
}
}
if !isTransmitterAServer { //Self data is considered as correct // todo add stuff
messageReceivedJSON.Body, err = db.Get_transaction(transToCheck.Id) //The client only gives the transaction Id. Future root has to set the data corresponding to this Id
if err != nil { if ack.Id != "" {
fmt.Println(err.Error()) if transactionToRate.Receiver != trans.Receiver {
return -1 ack.AmountOfCorrectNode = 0
ack.TotalNodes = 1
}
if transactionToRate.Sender != trans.Sender {
ack.AmountOfCorrectNode = 0
ack.TotalNodes = 1
}
if transactionToRate.Amount != trans.Amount {
ack.AmountOfCorrectNode = 0
ack.TotalNodes = 1
} }
} else {
if db.Is_transaction_valid(transToCheck) == -1 {
selfNodeAnswerVote.Percentage = 0.0
} }
if ack.TotalNodes == 0 {
ack.AmountOfCorrectNode = 1
ack.TotalNodes = 1
} }
if !isTransmitterAServer { var newAck AckTransaction
reach := false
count := 0
limit := len(config.Neighbours)
if stimulatedByClient {
reach = true reach = true
infosNode.Send_to_all_neighbours(messageReceivedJSON, portString) //vote sent to children go sendVoteToAllNeighbours(config, trans, parentAddress)
} }
numberOfNeighbours := infosNode.Get_number_of_neighbours()
//fmt.Printf("count:%d, nb of neighbours: %d\n",count, numberOfNeighbours)
for count < numberOfNeighbours {
if (count != 0 && isTransmitterAServer) || !isTransmitterAServer { //Potential skip to avoid two consecutives waiting
messageReceivedJSON, err, _, addrTransmitter = mess.Wait_and_get_message(ln) var mess Message
for count < limit {
if count != 0 || reach {
fmt.Println("Count is ", count, " to ", limit)
connection, err := server.Accept()
if err != nil { if err != nil {
fmt.Println("Error during waiting a message:", err.Error()) fmt.Println("Error accepting: ", err.Error())
return -1 err = nil
} continue
} }
fmt.Println("*****************************************")
fmt.Println("Processing client request number ", count)
fmt.Println("The connection is ", connection)
fmt.Println("The remote address is ", connection.RemoteAddr())
fmt.Println("The local address is ", connection.LocalAddr())
fmt.Println("*****************************************")
count++ err = json.NewDecoder(connection).Decode(&mess)
if reach == false {
reach = true
idParent, err = infosNode.Get_id_of_address(addrTransmitter)
if err != nil { if err != nil {
fmt.Println(err.Error()) fmt.Println("Error while decoding the transactionInDatabase", err)
return -1 err = nil
continue
} }
infosNode.Send_to_all_neighbours_except(messageReceivedJSON, []uint8{idParent}, portString) //vote sent to children
} else { //It can be a message from a child or not
if messageReceivedJSON.Job == "vote_answer" { //It's a child
voteAnswerReceived := mess.Extract_vote_answer_from_message(messageReceivedJSON)
var nbOfTransValids float64 = selfNodeAnswerVote.Percentage*float64(selfNodeAnswerVote.TotalSamples) + voteAnswerReceived.Percentage*float64(voteAnswerReceived.TotalSamples)
selfNodeAnswerVote.TotalSamples += voteAnswerReceived.TotalSamples
selfNodeAnswerVote.Percentage = nbOfTransValids / float64(selfNodeAnswerVote.TotalSamples)
} //else nothing to do
if mess.MessageType == "AckResponse" {
var body map[string]interface{} = mess.MessageBody.(map[string]interface{})
newAck.Id = body["id"].(string)
newAck.AmountOfCorrectNode = body["amountOfCorrectNode"].(int)
newAck.TotalNodes = body["totalNodes"].(int)
if ack.Id == newAck.Id {
ack.TotalNodes += newAck.TotalNodes
ack.AmountOfCorrectNode += newAck.AmountOfCorrectNode
} }
fmt.Println("Node correct : ", ack.AmountOfCorrectNode, "out of ", ack.TotalNodes)
} }
//Sends the answer of the vote to the parent or client
var answerVoteToSendJSON mess.Message
answerVoteToSendJSON.Job = "vote_answer"
answerVoteToSendJSON.Body = selfNodeAnswerVote
if !isTransmitterAServer { //The node is the root
//Sends to the client
err = encoderOnStream.Encode(answerVoteToSendJSON)
if err != nil {
fmt.Printf("Error, impossible to write the structure in JSON on the stream: ", err)
} }
} else { count++ // received message
go infosNode.Send_to_neighbour(idParent, answerVoteToSendJSON, portString) if !reach {
reach = true
go sendVoteToAllNeighbours(config, trans, parentAddress)
}
} }
if stimulatedByClient {
*/ fmt.Println("***********************************")
fmt.Println("Transaction has been rated")
fmt.Println("Node correct : ", ack.AmountOfCorrectNode, "out of ", ack.TotalNodes)
fmt.Println("***********************************")
go sendAckToNeighbour(config, ack, parentAddress)
}
return ack return ack
} }
func sendVoteToAllNeighbours(config Config, trans Transaction, parentIp string) {
for neighbour := range config.Neighbours {
ip := config.Neighbours[neighbour].Address
port := strconv.Itoa(config.Neighbours[neighbour].Port)
address := ip + ":" + port
if address != parentIp {
go sendVoteToNeighbour(config, trans, address)
}
}
}
func fake(authenticTrans Transaction, fakeTrans Transaction) { func fake(authenticTrans Transaction, fakeTrans Transaction) {
} }
...@@ -172,8 +205,10 @@ func printTransaction(trans Transaction) { ...@@ -172,8 +205,10 @@ func printTransaction(trans Transaction) {
} }
func listAllTransactions() { func listAllTransactions() {
for _, transaction := range DB { for i, transaction := range DB {
fmt.Println("***********INDEX N=,", i, "****************")
printTransaction(transaction) printTransaction(transaction)
fmt.Println("***********************************")
} }
} }
...@@ -294,10 +329,23 @@ func processClient(connection net.Conn, server net.Listener, config Config, stim ...@@ -294,10 +329,23 @@ func processClient(connection net.Conn, server net.Listener, config Config, stim
trans.Receiver = body["receiver"].(string) trans.Receiver = body["receiver"].(string)
trans.Sender = body["sender"].(string) trans.Sender = body["sender"].(string)
trans.Amount = body["amount"].(string) trans.Amount = body["amount"].(string)
for _, transaction := range DB {
if transaction.Id == trans.Id {
return
}
}
processTransaction(server, config, trans, stimulatedByClient) processTransaction(server, config, trans, stimulatedByClient)
} else if mess.MessageType == "rate" { } else if mess.MessageType == "rate" {
fmt.Println("Received a rate") fmt.Println("Received a rate")
processRate(server, config, mess.MessageBody.(AckTransaction)) var trans Transaction
var body map[string]interface{} = mess.MessageBody.(map[string]interface{})
trans.Id = body["id"].(string)
trans.Receiver = body["receiver"].(string)
trans.Sender = body["sender"].(string)
trans.Amount = body["amount"].(string)
printTransaction(trans)
// todo change this for cloud
vote(server, trans, config, connection.LocalAddr().String(), stimulatedByClient)
} else if mess.MessageType == "fake" { } else if mess.MessageType == "fake" {
fmt.Println("Received a fake") fmt.Println("Received a fake")
fmt.Println("Not yet implemented") fmt.Println("Not yet implemented")
...@@ -309,10 +357,6 @@ func processClient(connection net.Conn, server net.Listener, config Config, stim ...@@ -309,10 +357,6 @@ func processClient(connection net.Conn, server net.Listener, config Config, stim
} }
} }
func processRate(server net.Listener, config Config, transaction AckTransaction) {
}
func processTransaction(server net.Listener, config Config, trans Transaction, stimulatedByClient bool) { func processTransaction(server net.Listener, config Config, trans Transaction, stimulatedByClient bool) {
fmt.Println("Processing transaction") fmt.Println("Processing transaction")
printTransaction(trans) printTransaction(trans)
...@@ -412,10 +456,9 @@ func userInputLoop(config Config, isAlsoServer bool) { ...@@ -412,10 +456,9 @@ func userInputLoop(config Config, isAlsoServer bool) {
fmt.Println() fmt.Println()
fmt.Println("Please enter the operation you want to do") fmt.Println("Please enter the operation you want to do")
fmt.Println("1. Create a transaction") fmt.Println("1. Create a transaction")
fmt.Println("2. (client) Rate transaction") fmt.Println("2. Rate a transaction (from the client)")
fmt.Println("3. Fabricate a fake transaction") fmt.Println("3. Fabricate a fake transaction")
fmt.Println("4. Print all transactions") fmt.Println("4. Print all transactions")
fmt.Println("5. Rate a transaction")
fmt.Println("8. Exit") fmt.Println("8. Exit")
fmt.Print("Your choice: ") fmt.Print("Your choice: ")
_, err := fmt.Scanln(&operation) _, err := fmt.Scanln(&operation)
...@@ -432,6 +475,7 @@ func userInputLoop(config Config, isAlsoServer bool) { ...@@ -432,6 +475,7 @@ func userInputLoop(config Config, isAlsoServer bool) {
//createTransaction(newTrans) //createTransaction(newTrans)
} else { } else {
newTrans := userCreatedTransaction(config) newTrans := userCreatedTransaction(config)
addTransactionToDb(newTrans)
printAllNeighbours(config) printAllNeighbours(config)
fmt.Println("TRANSACTION READY TO BE SENT") fmt.Println("TRANSACTION READY TO BE SENT")
fmt.Println("Please enter the ID of the neighbour you want to send the transaction to") fmt.Println("Please enter the ID of the neighbour you want to send the transaction to")
...@@ -452,7 +496,7 @@ func userInputLoop(config Config, isAlsoServer bool) { ...@@ -452,7 +496,7 @@ func userInputLoop(config Config, isAlsoServer bool) {
case "2": case "2":
fmt.Println("You chose to rate a transaction") fmt.Println("You chose to rate a transaction")
listAllTransactions() listAllTransactions()
fmt.Print("\nPlease enter the ID of the transaction you want to rate:") fmt.Print("\nPlease enter the index of the transaction you want to rate:")
var transID string var transID string
_, err := fmt.Scanln(&transID) _, err := fmt.Scanln(&transID)
if err != nil { if err != nil {
...@@ -477,7 +521,9 @@ func userInputLoop(config Config, isAlsoServer bool) { ...@@ -477,7 +521,9 @@ func userInputLoop(config Config, isAlsoServer bool) {
fmt.Println("error :", err.Error()) fmt.Println("error :", err.Error())
os.Exit(1) os.Exit(1)
} }
sendVoteToNeighbour(config, DB[transIDInt], config.Neighbours[neighbourIDInt].Address, strconv.Itoa(config.Neighbours[neighbourIDInt].Port)) address := config.Neighbours[neighbourIDInt].Address + ":" + strconv.Itoa(config.Neighbours[neighbourIDInt].Port)
fmt.Println("Sending rate demand to ", address)
sendVoteToNeighbour(config, DB[transIDInt], address)
break break
case "3": case "3":
fmt.Println("You chose to fabricate a fake transaction") fmt.Println("You chose to fabricate a fake transaction")
...@@ -502,8 +548,56 @@ func userInputLoop(config Config, isAlsoServer bool) { ...@@ -502,8 +548,56 @@ func userInputLoop(config Config, isAlsoServer bool) {
} }
} }
func sendVoteToNeighbour(config Config, trans Transaction, address string, itoa string) { func sendVoteToNeighbour(config Config, trans Transaction, address string) {
fmt.Println()
fmt.Println("Trying to connect to ", address)
conn, err := net.Dial(ConnectionType, address)
if err != nil {
fmt.Println("Error while connecting to the neighbour", err)
os.Exit(1)
}
mess := Message{
MessageType: "rate",
MessageBody: trans,
}
fmt.Println("Sending message to neighbour", mess)
encoder := json.NewEncoder(conn)
err = encoder.Encode(mess)
if err != nil {
fmt.Println("Error while encoding the transaction", err)
os.Exit(1)
}
conn.Close()
fmt.Println("MessageBody successfully sent to neighbour")
}
func sendAckToNeighbour(config Config, ack AckTransaction, address string) {
fmt.Println()
fmt.Println("Trying to connect to ", address)
conn, err := net.Dial(ConnectionType, address)
if err != nil {
fmt.Println("Error while connecting to the neighbour", err)
os.Exit(1)
}
mess := Message{
MessageType: "AckResponse",
MessageBody: ack,
}
fmt.Println("Sending message to neighbour", mess)
encoder := json.NewEncoder(conn)
err = encoder.Encode(mess)
if err != nil {
fmt.Println("Error while encoding the transaction", err)
os.Exit(1)
}
conn.Close()
fmt.Println("MessageBody successfully sent to neighbour")
} }
func main() { func main() {
......
...@@ -4,7 +4,7 @@ port: 5001 ...@@ -4,7 +4,7 @@ port: 5001
neighbours: neighbours:
- id: 2 - id: 2
address: "127.0.0.3" address: "127.0.0.3"
port: 5002 port: 5003
- id: 3 - id: 3
address: "127.0.0.4" address: "127.0.0.4"
port: 5004 port: 5004
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment