From 498f7ad5b76c413062bc8818cfa6bf06adb13ebf Mon Sep 17 00:00:00 2001 From: "Richard T. Carback III" <rick.carback@gmail.com> Date: Mon, 21 Mar 2022 17:47:13 +0000 Subject: [PATCH] Implement Triggers and Fingerprints manager objects, WIP handler2 function implementation. --- interfaces/networkManager.go | 40 +++--- network/fingerprints.go | 131 ------------------- network/message/fingerprints.go | 111 +++++++++++++++++ network/{ => message}/fingerprints_test.go | 0 network/message/handler.go | 105 ++++------------ network/message/manager.go | 7 ++ network/{ => message}/triggers.go | 138 ++++++++++----------- network/{ => message}/triggers_test.go | 0 8 files changed, 236 insertions(+), 296 deletions(-) delete mode 100644 network/fingerprints.go create mode 100644 network/message/fingerprints.go rename network/{ => message}/fingerprints_test.go (100%) rename network/{ => message}/triggers.go (55%) rename network/{ => message}/triggers_test.go (100%) diff --git a/interfaces/networkManager.go b/interfaces/networkManager.go index 34ab130ea..f6feba860 100644 --- a/interfaces/networkManager.go +++ b/interfaces/networkManager.go @@ -8,16 +8,18 @@ package interfaces import ( + "time" + "gitlab.com/elixxir/client/interfaces/message" "gitlab.com/elixxir/client/interfaces/params" "gitlab.com/elixxir/client/network/gateway" "gitlab.com/elixxir/client/stoppable" + "gitlab.com/elixxir/comms/mixmessages" "gitlab.com/elixxir/comms/network" "gitlab.com/elixxir/crypto/e2e" "gitlab.com/elixxir/primitives/format" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/id/ephemeral" - "time" ) type NetworkManager interface { @@ -115,12 +117,12 @@ type NetworkManager interface { // type - a descriptive string of the trigger. Generally used in notifications // source - a byte buffer of related data. Generally used in notifications. // Example: Sender ID - AddTrigger(trigger Trigger, response MessageProcessorTrigger) error + AddTrigger(trigger Trigger, response MessageProcessor) error // RemoveTrigger - If only a single response is associated with the preimage, 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, all triggers for the preimage will be removed - RemoveTrigger(preimage []byte, response MessageProcessorTrigger) error + RemoveTrigger(preimage Preimage, response MessageProcessor) error // TrackTriggers - Registers a callback which will get called every time triggers change. // It will receive the triggers list every time it is modified. @@ -129,6 +131,8 @@ type NetworkManager interface { TrackTriggers(func(triggers []Trigger)) } +type Preimage [32]byte + type Identity struct { // Identity EphId ephemeral.Id @@ -147,24 +151,30 @@ type IdentityParams struct { EndValid time.Time // Timestamp when the ephID stops being valid // Makes the identity not store on disk + // When an ephemeral identity is deleted, all fingerprints & triggers + // associated with it also delete. + // TODO: This should not be confused with EphID for checking + // when messages are for the the user. That's a different type + // of Ephemeral in this context. Ephemeral bool } type Trigger struct { - Preimage []byte - Type string - Source []byte -} - -type MessageProcessorFP interface { - Process(message format.Message, fingerprint format.Fingerprint) - MarkFingerprintUsed(fingerprint format.Fingerprint) + Preimage + Type string + Source []byte } -type MessageProcessorTrigger interface { - Process(message format.Message, preimage []byte, Type string, source []byte) - Equals(trigger MessageProcessorTrigger) bool - String() string +type MessageProcessor interface { + // Process decrypts and hands off the message to its internal down + // stream message processing system. + // CRITICAL: Fingerprints should never be used twice. Process must + // denote, in long term storage, usage of a fingerprint and that + // fingerprint must not be added again during application load. + // It is a security vulnerability to reuse a fingerprint. It leaks + // privacy and can lead to compromise of message contents and integrity. + Process(message format.Message, receptionID Identity, + round *mixmessages.RoundInfo) } //type Ratchet interface { diff --git a/network/fingerprints.go b/network/fingerprints.go deleted file mode 100644 index 4c44331bb..000000000 --- a/network/fingerprints.go +++ /dev/null @@ -1,131 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// 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 - -import ( - "github.com/pkg/errors" - "gitlab.com/elixxir/client/interfaces" - "gitlab.com/elixxir/primitives/format" - "sync" -) - -// Processor is an object which ties an interfaces.MessageProcessorFP -// to a lock. This prevents the processor from being used in multiple -// different threads. -type Processor struct { - interfaces.MessageProcessorFP - sync.Mutex -} - -// NewFingerprints is a constructor function for the Processor object. -func newProcessor(mp interfaces.MessageProcessorFP) *Processor { - return &Processor{ - MessageProcessorFP: mp, - Mutex: sync.Mutex{}, - } -} - -// Fingerprints is a thread-safe map, mapping format.Fingerprint's to -// a Processor object. -type Fingerprints struct { - fingerprints map[format.Fingerprint]*Processor - sync.RWMutex -} - -// NewFingerprints is a constructor function for the Fingerprints tracker. -func NewFingerprints() *Fingerprints { - return &Fingerprints{ - fingerprints: make(map[format.Fingerprint]*Processor), - RWMutex: sync.RWMutex{}, - } -} - -// Get is a thread-safe getter for the Fingerprints map. Get returns the mapped -// processor and true (representing that it exists in the map) if the provided -// fingerprint has an entry. Otherwise, Get returns nil and false. -func (f *Fingerprints) Get(fingerprint format.Fingerprint) (*Processor, bool) { - f.RLock() - defer f.RUnlock() - fp, exists := f.fingerprints[fingerprint] - if !exists { - return nil, false - } - return fp, true -} - -// AddFingerprint is a thread-safe setter for the Fingerprints map. AddFingerprint -// maps the given fingerprint key to the processor value. If there is already -// an entry for this fingerprint, the method returns with no write operation. -func (f *Fingerprints) AddFingerprint(fingerprint format.Fingerprint, - processor interfaces.MessageProcessorFP) { - f.Lock() - defer f.Unlock() - - f.addFingerprint(fingerprint, processor) - -} - -// AddFingerprints is a thread-safe setter for multiple entries into -// the Fingerprints map. If there is not a 1:1 relationship between -// fingerprints and processors slices (i.e. the lengths of these slices -// are equivalent), an error will be returned. -// Otherwise, each fingerprint is written to the associated processor. -// If there is already an entry for the given fingerprint/processor pair, -// no write operation will occur for this pair. -func (f *Fingerprints) AddFingerprints(fps []format.Fingerprint, - processors []interfaces.MessageProcessorFP) error { - f.Lock() - defer f.Unlock() - - if len(fps) != len(processors) { - return errors.Errorf("Canot perform a batch add when there are "+ - "not an equal amount of fingerprints and processors. "+ - "Given %d fingerprints and %d processors.", len(fps), len(processors)) - } - - for i, fp := range fps { - f.addFingerprint(fp, processors[i]) - } - - return nil -} - -// addFingerprint is a non-thread-safe helper function which writes a Processor -// to the given fingerprint key. If an entry already exists for this fingerprint key, -// no write operation occurs. -func (f *Fingerprints) addFingerprint(fingerprint format.Fingerprint, - processor interfaces.MessageProcessorFP) { - - if _, exists := f.fingerprints[fingerprint]; exists { - return - } - - newMsgProc := newProcessor(processor) - - f.fingerprints[fingerprint] = newMsgProc -} - -// RemoveFingerprint is a thread-safe deletion operation on the Fingerprints map. -// It will remove the entry for the given fingerprint from the map. -func (f *Fingerprints) RemoveFingerprint(fingerprint format.Fingerprint) { - f.Lock() - defer f.Unlock() - - delete(f.fingerprints, fingerprint) -} - -// RemoveFingerprints is a thread-safe batch deletion operation on the Fingerprints map. -// It will remove the entries for the given fingerprints from the map. -func (f *Fingerprints) RemoveFingerprints(fingerprint []format.Fingerprint) { - f.Lock() - defer f.Unlock() - - for _, fp := range fingerprint { - delete(f.fingerprints, fp) - } -} diff --git a/network/message/fingerprints.go b/network/message/fingerprints.go new file mode 100644 index 000000000..fa4091163 --- /dev/null +++ b/network/message/fingerprints.go @@ -0,0 +1,111 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright © 2020 xx network SEZC // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file // +/////////////////////////////////////////////////////////////////////////////// + +package message + +import ( + "sync" + + "github.com/pkg/errors" + "gitlab.com/elixxir/client/interfaces" + "gitlab.com/elixxir/primitives/format" + "gitlab.com/xx_network/primitives/id" +) + +// FingerprintsManager is a thread-safe map, mapping format.Fingerprint's to +// a Processor object. +type FingerprintsManager struct { + fpMap map[id.ID]map[format.Fingerprint]interfaces.MessageProcessor + sync.Mutex +} + +// NewFingerprints is a constructor function for the Fingerprints tracker. +func NewFingerprints() *FingerprintsManager { + return &FingerprintsManager{ + fpMap: make(map[id.ID]map[format.Fingerprint]interfaces.MessageProcessor), + } +} + +// Pop returns the associated processor to the fingerprint and removes +// it from our list. +// CRITICAL: it is never ok to process a fingerprint twice. This is a security +// vulnerability. +func (f *FingerprintsManager) pop(clientID *id.ID, + fingerprint format.Fingerprint) ( + interfaces.MessageProcessor, bool) { + f.Lock() + defer f.Unlock() + cid := *clientID + if idFpmap, exists := f.fpMap[cid]; exists { + if proc, exists := idFpmap[fingerprint]; exists { + delete(f.fpMap[cid], fingerprint) + if len(f.fpMap[cid]) == 0 { + delete(f.fpMap, cid) + } + return proc, true + } + } + + return nil, false +} + +// AddFingerprint is a thread-safe setter for the Fingerprints +// map. AddFingerprint maps the given fingerprint key to the processor +// value. If there is already an entry for this fingerprint, the +// method returns with no write operation. +func (f *FingerprintsManager) Add(clientID *id.ID, + fingerprint format.Fingerprint, + mp interfaces.MessageProcessor) error { + f.Lock() + defer f.Unlock() + + cid := *clientID + + if _, exists := f.fpMap[cid]; !exists { + f.fpMap[cid] = make( + map[format.Fingerprint]interfaces.MessageProcessor) + } + + if _, exists := f.fpMap[cid][fingerprint]; exists { + return errors.Errorf("fingerprint %s already exists", + fingerprint) + } + + f.fpMap[cid][fingerprint] = mp + return nil +} + +// Delete is a thread-safe deletion operation on the Fingerprints map. +// It will remove the entry for the given fingerprint from the map. +func (f *FingerprintsManager) Delete(clientID *id.ID, + fingerprint format.Fingerprint) { + f.Lock() + defer f.Unlock() + + cid := *clientID + + if _, exists := f.fpMap[cid]; exists { + if _, exists = f.fpMap[cid][fingerprint]; exists { + delete(f.fpMap[cid], fingerprint) + } + if len(f.fpMap[cid]) == 0 { + delete(f.fpMap, cid) + } + } +} + +// DeleteClient is a thread-safe deletion operation on the Fingerprints map. +// It will remove all entres for the given clientID from the map. +func (f *FingerprintsManager) DeleteClient(clientID *id.ID, + fingerprint format.Fingerprint) { + f.Lock() + defer f.Unlock() + + cid := *clientID + + delete(f.fpMap, cid) +} diff --git a/network/fingerprints_test.go b/network/message/fingerprints_test.go similarity index 100% rename from network/fingerprints_test.go rename to network/message/fingerprints_test.go diff --git a/network/message/handler.go b/network/message/handler.go index 5f72f8641..9ffb92bab 100644 --- a/network/message/handler.go +++ b/network/message/handler.go @@ -9,7 +9,10 @@ package message import ( "fmt" + "time" + jww "github.com/spf13/jwalterweatherman" + "gitlab.com/elixxir/client/interfaces" "gitlab.com/elixxir/client/interfaces/message" "gitlab.com/elixxir/client/interfaces/preimage" "gitlab.com/elixxir/client/stoppable" @@ -19,7 +22,6 @@ import ( "gitlab.com/elixxir/primitives/format" "gitlab.com/elixxir/primitives/states" "gitlab.com/xx_network/primitives/id" - "time" ) func (m *Manager) handleMessages(stop *stoppable.Single) { @@ -162,95 +164,35 @@ func (m *Manager) handleMessage(ecrMsg format.Message, bundle Bundle, edge *edge } } - -func (m *Manager) handleMessage2(ecrMsg format.Message, bundle Bundle) { - fingerprint := ecrMsg.GetKeyFP() - msgDigest := ecrMsg.Digest() - identity := bundle.Identity - - round := bundle.RoundInfo - newID := // todo use new id systme from ticket - { - ID id.ID - ephID ephemeral.Id - } - - // If we have a fingerprint, process it. - messageProc, exists := m.fingerprints.Pop(fingerprint) { - // note scope here is all broken, fix... - m.fingers.Lock() - defer m.fingersUnlock() - mp, ok := m.fingers[fingerprint] - if ok { - mp.MarkFingerprintUsed(fingerprint) - delete(m.fingers, fingerprint) - return mp, true - } - return nil, false - } - if exists { - // in progress is a future project. - // m.inprogress.Add({fingerprint, ecrMsg, newID, round}) - go messageProc.Process(ecrMsg, newID, round) - return - } - - triggerProc, trigger, exists := m.triggers.Lookup( - ecrMsg.GetIdentityFP(), ecrMsgContents) - if exists { - go triggerProc.Process(ecrMsg, newID, round, trigger) - return - } else { - // TODO: delete this else block because it should not be needed. - jww.INFO.Printf("checking backup %v", preimage.MakeDefault(identity.Source)) - // //if it doesnt exist, check against the default fingerprint for the identity - // forMe = fingerprint2.CheckIdentityFP(ecrMsg.GetIdentityFP(), - // ecrMsgContents, preimage.MakeDefault(identity.Source)) - } - - if jww.GetLogThreshold() == jww.LevelTrace { - expectedFP := fingerprint2.IdentityFP(ecrMsgContents, - preimage.MakeDefault(identity.Source)) - jww.TRACE.Printf("Message for %d (%s) failed identity "+ - "check: %v (expected-default) vs %v (received)", - identity.EphId, - identity.Source, expectedFP, ecrMsg.GetIdentityFP()) - } - im := fmt.Sprintf("Garbled/RAW Message: keyFP: %v, round: %d"+ - "msgDigest: %s, not determined to be for client", ecrMsg.GetKeyFP(), bundle.Round, ecrMsg.Digest()) - m.Internal.Events.Report(1, "MessageReception", "Garbled", im) - m.Session.GetGarbledMessages().Add(ecrMsg) -} - func (m *Manager) handleMessage2(ecrMsg format.Message, bundle Bundle) { fingerprint := ecrMsg.GetKeyFP() - msgDigest := ecrMsg.Digest() + // msgDigest := ecrMsg.Digest() identity := bundle.Identity round := bundle.RoundInfo - newID := // todo use new id systme from ticket - { - ID id.ID - ephID ephemeral.Id - } + // newID := *id.ID{} // todo use new id systme from ticket + // { + // ID id.ID + // ephID ephemeral.Id + // } + var receptionID interfaces.Identity // If we have a fingerprint, process it. - //Lock - messageProc, fpLock, exists := m.fingerprints[fingerprint] - // Unlock - if exists { - fpLock.Lock() - defer fpLock.Unlock() - messageProc.MarkFingerprintUsed(fingerprint) - messageProc.Process(ecrMsg, newID, round) - delete(m.fingerprints, fingerprint) + if proc, exists := m.pop(fingerprint); exists { + proc.Process(ecrMsg, receptionID, round) return } - triggerProc, trigger, exists := m.triggers.Lookup( - ecrMsg.GetIdentityFP(), ecrMsgContents) + triggers, exists := m.get(ecrMsg.GetIdentityFP(), ecrMsg.GetContents()) if exists { - go triggerProc.Process(ecrMsg, newID, round, trigger) + for _, t := range triggers { + go t.Process(ecrMsg, receptionID, round) + } + if len(triggers) == 0 { + jww.ERROR.Printf("empty trigger list for %s", + ecrMsg.GetIdentityFP()) // get preimage + ) + } return } else { // TODO: delete this else block because it should not be needed. @@ -261,7 +203,7 @@ func (m *Manager) handleMessage2(ecrMsg format.Message, bundle Bundle) { } if jww.GetLogThreshold() == jww.LevelTrace { - expectedFP := fingerprint2.IdentityFP(ecrMsgContents, + expectedFP := fingerprint2.IdentityFP(ecrMsg.GetContents(), preimage.MakeDefault(identity.Source)) jww.TRACE.Printf("Message for %d (%s) failed identity "+ "check: %v (expected-default) vs %v (received)", @@ -269,7 +211,8 @@ func (m *Manager) handleMessage2(ecrMsg format.Message, bundle Bundle) { identity.Source, expectedFP, ecrMsg.GetIdentityFP()) } im := fmt.Sprintf("Garbled/RAW Message: keyFP: %v, round: %d"+ - "msgDigest: %s, not determined to be for client", ecrMsg.GetKeyFP(), bundle.Round, ecrMsg.Digest()) + "msgDigest: %s, not determined to be for client", + ecrMsg.GetKeyFP(), bundle.Round, ecrMsg.Digest()) m.Internal.Events.Report(1, "MessageReception", "Garbled", im) m.Session.GetGarbledMessages().Add(ecrMsg) } diff --git a/network/message/manager.go b/network/message/manager.go index 0ac5eeceb..a9422cc50 100644 --- a/network/message/manager.go +++ b/network/message/manager.go @@ -10,6 +10,7 @@ package message import ( "encoding/base64" "fmt" + jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/interfaces/params" "gitlab.com/elixxir/client/network/gateway" @@ -31,6 +32,9 @@ type Manager struct { nodeRegistration chan network.NodeGateway networkIsHealthy chan bool triggerGarbled chan struct{} + + FingerprintsManager + TriggersManager } func NewManager(internal internal.Internal, param params.Network, @@ -54,6 +58,9 @@ func NewManager(internal internal.Internal, param params.Network, } m.blacklistedNodes[string(decodedId)] = nil } + + m.FingerprintsManager = *NewFingerprints() + m.TriggersManager = *NewTriggers() return &m } diff --git a/network/triggers.go b/network/message/triggers.go similarity index 55% rename from network/triggers.go rename to network/message/triggers.go index 33da8982e..453c45cc5 100644 --- a/network/triggers.go +++ b/network/message/triggers.go @@ -5,14 +5,15 @@ // LICENSE file // /////////////////////////////////////////////////////////////////////////////// -package network +package message import ( - "encoding/base64" + "sync" + "github.com/pkg/errors" "gitlab.com/elixxir/client/interfaces" - fingerprint2 "gitlab.com/elixxir/crypto/fingerprint" - "sync" + "gitlab.com/elixxir/crypto/fingerprint" + "gitlab.com/xx_network/primitives/id" ) /* Trigger - predefined hash based tags appended to all cmix messages @@ -35,17 +36,17 @@ Triggers are ephemeral to the session. When starting a new client, all triggers re-added before StartNetworkFollower is called. */ -type Triggers struct { - triggers map[string][]*Trigger - sync.RWMutex +type TriggersManager struct { + tmap map[id.ID]map[interfaces.Preimage][]trigger + sync.Mutex } -type Trigger struct { +type trigger struct { interfaces.Trigger - interfaces.MessageProcessorTrigger + interfaces.MessageProcessor } -func NewTriggers() *Triggers { +func NewTriggers() *TriggersManager { // todo: implement me return nil } @@ -64,23 +65,21 @@ func NewTriggers() *Triggers { // - privatizing the state-changing methods // - leaking lookup on this layer and migrating the state modifiation methods // a layer down in a sepearate package -func (t *Triggers) Lookup(receivedIdentityFp, - ecrMsgContents []byte) (triggers []*Trigger, forMe bool) { - t.RLock() - defer t.RUnlock() - - for preimage, triggerList := range t.triggers { - preimageBytes, err := unmarshalPreimage(preimage) - if err != nil { - // fixme: panic here?, An error here would mean there's a bad - // key-value pair in the map (specifically the preimage-key is bad, - // as it should be base64 encoded). - } - // fixme, there probably needs to be a small refactor. - // Terminology and variable names are being used misused. For example: - // phrases like tag, preimage and identityFP are being used - // interchangeably in the code and it's getting unwieldy. - if fingerprint2.CheckIdentityFP(receivedIdentityFp, ecrMsgContents, preimageBytes) { +func (t *TriggersManager) get(clientID *id.ID, receivedIdentityFp, + ecrMsgContents []byte) ([]trigger, + bool) { + t.Lock() + defer t.Unlock() + cid := *clientID + + triggers, exists := t.tmap[cid] + if !exists { + return nil, false + } + + for pi, triggerList := range triggers { + if fingerprint.CheckIdentityFP(receivedIdentityFp, + ecrMsgContents, pi[:]) { return triggerList, true } } @@ -95,77 +94,78 @@ func (t *Triggers) Lookup(receivedIdentityFp, // type - a descriptive string of the trigger. Generally used in notifications // source - a byte buffer of related data. Generally used in notifications. // Example: Sender ID -func (t *Triggers) Add(trigger interfaces.Trigger, - response interfaces.MessageProcessorTrigger) error { +func (t *TriggersManager) Add(clientID *id.ID, newTrigger interfaces.Trigger, + response interfaces.MessageProcessor) { t.Lock() defer t.Unlock() - marshalledPreimage := marshalPreimage(trigger.Preimage) + newEntry := trigger{ + Trigger: newTrigger, + MessageProcessor: response, + } - newTrigger := &Trigger{ - Trigger: trigger, - MessageProcessorTrigger: response, + cid := *clientID + if _, exists := t.tmap[cid]; !exists { + t.tmap[cid] = make(map[interfaces.Preimage][]trigger) } - if existingTriggers, exists := t.triggers[marshalledPreimage]; exists { - // fixme Should there be a check if this response exists already? - t.triggers[marshalledPreimage] = append(existingTriggers, newTrigger) - return nil + pi := newTrigger.Preimage + if existingTriggers, exists := t.tmap[cid][pi]; exists { + t.tmap[cid][pi] = append(existingTriggers, newEntry) } - t.triggers[marshalledPreimage] = []*Trigger{newTrigger} + t.tmap[cid][pi] = []trigger{newEntry} - return nil } -// RemoveTrigger - If only a single response is associated with the preimage, +// Delete - If only a single response is associated with the preimage, // 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, // all triggers for the preimage will be removed. -func (t *Triggers) RemoveTrigger(preimage []byte, - response interfaces.MessageProcessorTrigger) error { +func (t *TriggersManager) Delete(clientID *id.ID, preimage interfaces.Preimage, + response interfaces.MessageProcessor) error { t.Lock() defer t.Unlock() - marshalledPreimage := marshalPreimage(preimage) + if response == nil { + return errors.Errorf("response cannot be nil when deleting") + } - triggers, exists := t.triggers[marshalledPreimage] + cid := *clientID + + idTmap, exists := t.tmap[cid] if !exists { - return errors.Errorf("No trigger with preimage %q found", - marshalledPreimage) + return nil } - if response == nil { - delete(t.triggers, marshalledPreimage) + triggers, exists := idTmap[preimage] + if !exists { return nil } - for _, trigger := range triggers { - if trigger.Equals(response) { - delete(t.triggers, marshalPreimage(trigger.Preimage)) - return nil + if len(triggers) == 1 && triggers[0].MessageProcessor == response { + if len(idTmap) == 1 { + delete(t.tmap, cid) + } else { + delete(t.tmap[cid], preimage) } } - 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? + for idx, cur := range triggers { + if cur.MessageProcessor == response { + t.tmap[cid][preimage] = append(triggers[:idx], + triggers[idx+1:]...) + return nil + } + } -// marshalPreimage is a helper which encodes the preimage byte data to -// a base64 encoded string. -func marshalPreimage(pi []byte) string { - return base64.StdEncoding.EncodeToString(pi) + return nil } -// unmarshalPreimage is a helper which decodes the preimage base64 string to -// bytes. -func unmarshalPreimage(data string) ([]byte, error) { - decoded, err := base64.StdEncoding.DecodeString(data) - if err != nil { - return nil, err - } +// DeleteClient - delete the mapping associated with an ID +func (t *TriggersManager) DeleteClient(clientID *id.ID) { + t.Lock() + defer t.Unlock() - return decoded, nil + delete(t.tmap, *clientID) } diff --git a/network/triggers_test.go b/network/message/triggers_test.go similarity index 100% rename from network/triggers_test.go rename to network/message/triggers_test.go -- GitLab