Skip to content
Snippets Groups Projects
Commit 1a5df79a authored by Josh Brooks's avatar Josh Brooks
Browse files

WIP: Finalize triggers implementation

parent 9750afa8
No related branches found
No related tags found
4 merge requests!510Release,!207WIP: Client Restructure,!203Symmetric broadcast,!187Xx 3829/triggers
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
package interfaces package interfaces
import ( import (
"encoding/base64"
"gitlab.com/elixxir/client/interfaces/message" "gitlab.com/elixxir/client/interfaces/message"
"gitlab.com/elixxir/client/interfaces/params" "gitlab.com/elixxir/client/interfaces/params"
"gitlab.com/elixxir/client/network/gateway" "gitlab.com/elixxir/client/network/gateway"
...@@ -151,15 +150,8 @@ type IdentityParams struct { ...@@ -151,15 +150,8 @@ type IdentityParams struct {
Ephemeral bool Ephemeral bool
} }
type Preimage []byte
// key returns the key used to identify the Preimage in a map.
func (pi Preimage) String() string {
return base64.StdEncoding.EncodeToString(pi)
}
type Trigger struct { type Trigger struct {
Preimage Preimage Preimage []byte
Type string Type string
Source []byte Source []byte
} }
...@@ -172,6 +164,7 @@ type MessageProcessorFP interface { ...@@ -172,6 +164,7 @@ type MessageProcessorFP interface {
type MessageProcessorTrigger interface { type MessageProcessorTrigger interface {
Process(message format.Message, preimage []byte, Type string, source []byte) Process(message format.Message, preimage []byte, Type string, source []byte)
Equals(trigger MessageProcessorTrigger) bool Equals(trigger MessageProcessorTrigger) bool
String() string
} }
//type Ratchet interface { //type Ratchet interface {
......
...@@ -8,11 +8,33 @@ ...@@ -8,11 +8,33 @@
package network package network
import ( import (
"encoding/base64"
"github.com/pkg/errors" "github.com/pkg/errors"
"gitlab.com/elixxir/client/interfaces" "gitlab.com/elixxir/client/interfaces"
fingerprint2 "gitlab.com/elixxir/crypto/fingerprint"
"sync" "sync"
) )
/* Trigger - predefined hash based tags appended to all cmix messages
which, though trial hashing, are used to determine if a message applies
to this client
Triggers are used for 2 purposes - can be processed by the notifications system,
or can be used to implement custom non fingerprint processing of payloads.
I.E. key negotiation, broadcast negotiation
A tag is appended to the message of the format tag = H(H(messageContents),preimage)
and trial hashing is used to determine if a message adheres to a tag.
WARNING: If a preiamge is known by an adversary, they can determine which messages
are for the client.
Due to the extra overhead of trial hashing, triggers are processed after fingerprints.
If a fingerprint match occurs on the message, triggers will not be handled.
Triggers are ephemeral to the session. When starting a new client, all triggers must be
re-added before StartNetworkFollower is called.
*/
type Triggers struct { type Triggers struct {
triggers map[string][]*Trigger triggers map[string][]*Trigger
sync.RWMutex sync.RWMutex
...@@ -29,10 +51,22 @@ func NewTriggers() *Triggers { ...@@ -29,10 +51,22 @@ func NewTriggers() *Triggers {
} }
func (t *Triggers) Lookup(identityFp, func (t *Triggers) Lookup(identityFp,
ecrMsgContents []byte) (*Trigger, bool) { ecrMsgContents []byte) ([]*Trigger, bool) {
t.RLock() t.RLock()
defer t.RUnlock() defer t.RUnlock()
for preimage, triggers := range t.triggers {
preimageBytes, err := unmarshalPreimage(preimage)
if err != nil {
// fixme: panic here, this error would mean bad data is in the map
}
if fingerprint2.CheckIdentityFP(identityFp, ecrMsgContents, preimageBytes) {
return triggers, true
}
}
return nil, false
} }
// Add - Adds a trigger which can call a message // Add - Adds a trigger which can call a message
...@@ -47,19 +81,20 @@ func (t *Triggers) Add(trigger interfaces.Trigger, ...@@ -47,19 +81,20 @@ func (t *Triggers) Add(trigger interfaces.Trigger,
t.Lock() t.Lock()
defer t.Unlock() defer t.Unlock()
preimage := trigger.Preimage.String() marshalledPreimage := marshalPreimage(trigger.Preimage)
newTrigger := &Trigger{ newTrigger := &Trigger{
Trigger: trigger, Trigger: trigger,
MessageProcessorTrigger: response, MessageProcessorTrigger: response,
} }
if existingTriggers, exists := t.triggers[preimage]; exists { if existingTriggers, exists := t.triggers[marshalledPreimage]; exists {
t.triggers[preimage] = append(existingTriggers, newTrigger) // fixme Should there be a check if this response exists already?
t.triggers[marshalledPreimage] = append(existingTriggers, newTrigger)
return nil return nil
} }
t.triggers[preimage] = []*Trigger{newTrigger} t.triggers[marshalledPreimage] = []*Trigger{newTrigger}
return nil return nil
} }
...@@ -68,26 +103,45 @@ func (t *Triggers) Add(trigger interfaces.Trigger, ...@@ -68,26 +103,45 @@ func (t *Triggers) Add(trigger interfaces.Trigger,
// the entire preimage is removed. If there is more than one response, only // the entire preimage is removed. If there is more than one response, only
// the given response is removed. If nil is passed in for response, // the given response is removed. If nil is passed in for response,
// all triggers for the preimage will be removed. // all triggers for the preimage will be removed.
func (t *Triggers) RemoveTrigger(preimage interfaces.Preimage, func (t *Triggers) RemoveTrigger(preimage []byte,
response interfaces.MessageProcessorTrigger) error { response interfaces.MessageProcessorTrigger) error {
t.Lock() t.Lock()
defer t.Unlock() defer t.Unlock()
triggers, exists := t.triggers[preimage.String()] marshalledPreimage := marshalPreimage(preimage)
triggers, exists := t.triggers[marshalledPreimage]
if !exists { if !exists {
return errors.Errorf("No triggers exist with preimage %q", preimage.String()) return errors.Errorf("No trigger with preimage %q found",
marshalledPreimage)
} }
if response == nil { if response == nil {
delete(t.triggers, preimage.String()) delete(t.triggers, marshalledPreimage)
return nil return nil
} }
for _, trigger := range triggers { for _, trigger := range triggers {
if trigger.Equals(response) { if trigger.Equals(response) {
delete(t.triggers, trigger.Preimage.String()) delete(t.triggers, marshalPreimage(trigger.Preimage))
return nil
} }
} }
return nil return errors.Errorf("No response (%q) exists with preimage %q",
response.String(), marshalledPreimage)
}
// fixme: maybe make preimage a type or struct and place this in primitives?
func marshalPreimage(pi []byte) string {
return base64.StdEncoding.EncodeToString(pi)
}
func unmarshalPreimage(data string) ([]byte, error) {
decoded, err := base64.StdEncoding.DecodeString(data)
if err != nil {
return nil, err
}
return decoded, nil
} }
///////////////////////////////////////////////////////////////////////////////
// Copyright © 2020 xx network SEZC //
// //
// Use of this source code is governed by a license that can be found in the //
// LICENSE file //
///////////////////////////////////////////////////////////////////////////////
package network
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment