From c38ea10ec7198e43ce9cbf2f3dc1d89d2f34c6da Mon Sep 17 00:00:00 2001 From: tfn18001 Date: Wed, 20 Apr 2022 14:57:01 -0400 Subject: [PATCH] Added Duplicate-item PoM checking to Gossiper --- CTng/gossip/gossip_object.go | 2 +- CTng/gossip/gossiper.go | 4 +-- CTng/gossip/process_object.go | 55 ++++++++++++++++++++++++---------- CTng/server/Gossiper_server.go | 21 +++++++++---- 4 files changed, 58 insertions(+), 24 deletions(-) diff --git a/CTng/gossip/gossip_object.go b/CTng/gossip/gossip_object.go index 68e562f..3b64d7c 100644 --- a/CTng/gossip/gossip_object.go +++ b/CTng/gossip/gossip_object.go @@ -29,7 +29,7 @@ func (g Gossip_object) GetID(period_interval int64) Gossip_object_ID { } } -// This function is highly associated with this type, so I think it belongs here. +// GetCurrentTimestamp returns the current UTC timestamp in RFC3339 format func GetCurrentTimestamp() string { return time.Now().UTC().Format(time.RFC3339) } diff --git a/CTng/gossip/gossiper.go b/CTng/gossip/gossiper.go index 48698c3..369a93f 100644 --- a/CTng/gossip/gossiper.go +++ b/CTng/gossip/gossiper.go @@ -29,7 +29,7 @@ func Accuse(c *GossiperContext, url string) { // Sends a gossip object to all connected gossipers. // This function assumes you are passing valid data. ALWAYS CHECK BEFORE CALLING THIS FUNCTION. -func gossipData(c *GossiperContext, gossip_obj Gossip_object) error { +func GossipData(c *GossiperContext, gossip_obj Gossip_object) error { // Convert gossip object to JSON msg, err := json.Marshal(gossip_obj) if err != nil { @@ -64,7 +64,7 @@ func gossipData(c *GossiperContext, gossip_obj Gossip_object) error { } // Sends a gossip object to the owner of the object. -func sendToOwner(c *GossiperContext, obj Gossip_object) { +func SendToOwner(c *GossiperContext, obj Gossip_object) { // Convert gossip object to JSON msg, err := json.Marshal(obj) if err != nil { diff --git a/CTng/gossip/process_object.go b/CTng/gossip/process_object.go index ba8483c..ea00818 100644 --- a/CTng/gossip/process_object.go +++ b/CTng/gossip/process_object.go @@ -2,6 +2,7 @@ package gossip import ( "CTng/util" + "errors" "fmt" ) @@ -15,25 +16,25 @@ func ProcessValidObject(c *GossiperContext, obj Gossip_object) { var err error = nil switch obj.Type { case STH: - sendToOwner(c, obj) - err = gossipData(c, obj) + SendToOwner(c, obj) + err = GossipData(c, obj) case REVOCATION: - sendToOwner(c, obj) - err = gossipData(c, obj) + SendToOwner(c, obj) + err = GossipData(c, obj) case STH_FRAG: - sendToOwner(c, obj) - err = gossipData(c, obj) + SendToOwner(c, obj) + err = GossipData(c, obj) case GOSSIP_POM: - sendToOwner(c, obj) - err = gossipData(c, obj) + SendToOwner(c, obj) + err = GossipData(c, obj) case REVOCATION_FRAG: - err = gossipData(c, obj) + err = GossipData(c, obj) case ACCUSATION_FRAG: ProcessAccusation(c, obj) - err = gossipData(c, obj) + err = GossipData(c, obj) case APPLICATION_POM: - sendToOwner(c, obj) - err = gossipData(c, obj) + SendToOwner(c, obj) + err = GossipData(c, obj) default: fmt.Println("Recieved unsupported object type.") } @@ -42,10 +43,34 @@ func ProcessValidObject(c *GossiperContext, obj Gossip_object) { } } +// Process a valid gossip object which is a duplicate to another one. +// If the signature/payload is identical, then we can safely ignore the duplicate. +// Otherwise, we generate a PoM for two objects sent in the same period. +func ProcessDuplicateObject(c *GossiperContext, obj Gossip_object, dup Gossip_object) err { + if obj.Signature == dup.Signature && + obj.Payload == dup.Payload { + return nil + } else { + // Generate PoM + pom := Gossip_object{ + Application: obj.Application, + Type: GOSSIP_POM, + Signer: obj.Signer, + Signature: [2]string{obj.Signature[0], dup.Signature[0]}, + Payload: [2]string{obj.Payload[0], dup.Payload[0]}, + Timestamp: GetCurrentTimestamp(), + } + c.StoreObject(pom) + c.HasPom[obj.Payload[0]] = true + // Currently, we don't send PoMs. but if we did, we could do it here. + SendToOwner(c, pom) + return errors.New("Proof of Misbhevior Generated") + } +} + func ProcessInvalidObject(obj Gossip_object, e error) { // TODO: // Determine Conflict/misbehavior - // Log error // Send neccessary accusations } @@ -57,13 +82,13 @@ func ProcessAccusation(c *GossiperContext, acc Gossip_object) { fmt.Println(util.YELLOW+"Processed accusation against", acc.Payload[0], util.RESET) } if shouldGossip { - gossipData(c, acc) + GossipData(c, acc) } if pom != nil { fmt.Println(util.RED+"Generated POM for", acc.Payload[0], util.RESET) c.StoreObject(*pom) c.HasPom[acc.Payload[0]] = true // We do not currently gossip PoMs. - sendToOwner(c, *pom) + SendToOwner(c, *pom) } } diff --git a/CTng/server/Gossiper_server.go b/CTng/server/Gossiper_server.go index 9880b03..1487437 100644 --- a/CTng/server/Gossiper_server.go +++ b/CTng/server/Gossiper_server.go @@ -127,12 +127,17 @@ func handleGossip(c *gossip.GossiperContext, w http.ResponseWriter, r *http.Requ return } // Check for duplicate object. - _, found := c.GetObject(gossip_obj.GetID(c.Config.Public.Period_interval)) + stored_obj, found := c.GetObject(gossip_obj.GetID(c.Config.Public.Period_interval)) if found { // If the object is already stored, still return OK.{ fmt.Println("Duplicate:", gossip_obj.Type, getSenderURL(r)+".") - http.Error(w, "Gossip object already stored.", http.StatusOK) - // gossip.ProcessDuplicateObject(c, gossip_obj, stored_obj) + err := gossip.ProcessDuplicateObject(c, gossip_obj, stored_obj) + if err != nil { + http.Error(w, err.Error(), http.StatusOK) + } else { + http.Error(w, "Duplicate object.", http.StatusOK) + } + http.Error(w, "Recieved Duplicate Object.", http.StatusOK) return } else { fmt.Println(util.GREEN+"Recieved new, valid", gossip_obj.Type, "from "+getSenderURL(r)+".", util.RESET) @@ -165,12 +170,16 @@ func handleOwnerGossip(c *gossip.GossiperContext, w http.ResponseWriter, r *http fmt.Println(util.RED+"Owner sent invalid object.", util.RESET) http.Error(w, err.Error(), http.StatusBadRequest) } - _, found := c.GetObject(gossip_obj.GetID(c.Config.Public.Period_interval)) + stored_obj, found := c.GetObject(gossip_obj.GetID(c.Config.Public.Period_interval)) if found { // If the object is already stored, still return OK.{ fmt.Println("Recieved duplicate object from Owner.") - http.Error(w, "Gossip object already stored.", http.StatusOK) - // gossip.ProcessDuplicateObject(c, gossip_obj, stored_obj) + err := gossip.ProcessDuplicateObject(c, gossip_obj, stored_obj) + if err != nil { + http.Error(w, "Duplicate Object recieved!", http.StatusOK) + } else { + http.Error(w, err.Error(), http.StatusOK) + } return } else { // Prints the body of the post request to the server console