88 "math/big"
99 "strconv"
1010 "strings"
11+ "sync"
1112
1213 "github.com/lightninglabs/lightning-terminal/session"
1314 "go.etcd.io/bbolt"
@@ -78,6 +79,10 @@ type PrivacyMapTx interface {
7879 // RealToPseudo returns the pseudo value associated with the given real
7980 // value. If no such pair is found, then ErrNoSuchKeyFound is returned.
8081 RealToPseudo (real string ) (string , error )
82+
83+ // FetchAllPairs loads and returns the real-to-pseudo pairs in the form
84+ // of a PrivacyMapPairs struct.
85+ FetchAllPairs () (* PrivacyMapPairs , error )
8186}
8287
8388// privacyMapDB is an implementation of PrivacyMapDB.
@@ -169,6 +174,8 @@ type privacyMapTx struct {
169174}
170175
171176// NewPair inserts a new real-pseudo pair into the db.
177+ //
178+ // NOTE: this is part of the PrivacyMapTx interface.
172179func (p * privacyMapTx ) NewPair (real , pseudo string ) error {
173180 privacyBucket , err := getBucket (p .boltTx , privacyBucketKey )
174181 if err != nil {
@@ -194,6 +201,16 @@ func (p *privacyMapTx) NewPair(real, pseudo string) error {
194201 return err
195202 }
196203
204+ if len (realToPseudoBucket .Get ([]byte (real ))) != 0 {
205+ return fmt .Errorf ("an entry already exists for real " +
206+ "value: %x" , real )
207+ }
208+
209+ if len (pseudoToRealBucket .Get ([]byte (pseudo ))) != 0 {
210+ return fmt .Errorf ("an entry already exists for pseudo " +
211+ "value: %x" , pseudo )
212+ }
213+
197214 err = realToPseudoBucket .Put ([]byte (real ), []byte (pseudo ))
198215 if err != nil {
199216 return err
@@ -204,6 +221,8 @@ func (p *privacyMapTx) NewPair(real, pseudo string) error {
204221
205222// PseudoToReal will check the db to see if the given pseudo key exists. If
206223// it does then the real value is returned, else an error is returned.
224+ //
225+ // NOTE: this is part of the PrivacyMapTx interface.
207226func (p * privacyMapTx ) PseudoToReal (pseudo string ) (string , error ) {
208227 privacyBucket , err := getBucket (p .boltTx , privacyBucketKey )
209228 if err != nil {
@@ -230,6 +249,8 @@ func (p *privacyMapTx) PseudoToReal(pseudo string) (string, error) {
230249
231250// RealToPseudo will check the db to see if the given real key exists. If
232251// it does then the pseudo value is returned, else an error is returned.
252+ //
253+ // NOTE: this is part of the PrivacyMapTx interface.
233254func (p * privacyMapTx ) RealToPseudo (real string ) (string , error ) {
234255 privacyBucket , err := getBucket (p .boltTx , privacyBucketKey )
235256 if err != nil {
@@ -254,6 +275,38 @@ func (p *privacyMapTx) RealToPseudo(real string) (string, error) {
254275 return string (pseudo ), nil
255276}
256277
278+ // FetchAllPairs loads and returns the real-to-pseudo pairs.
279+ //
280+ // NOTE: this is part of the PrivacyMapTx interface.
281+ func (p * privacyMapTx ) FetchAllPairs () (* PrivacyMapPairs , error ) {
282+ privacyBucket , err := getBucket (p .boltTx , privacyBucketKey )
283+ if err != nil {
284+ return nil , err
285+ }
286+
287+ sessBucket := privacyBucket .Bucket (p .groupID [:])
288+ if sessBucket == nil {
289+ return nil , ErrNoSuchKeyFound
290+ }
291+
292+ realToPseudoBucket := sessBucket .Bucket (realToPseudoKey )
293+ if realToPseudoBucket == nil {
294+ return nil , ErrNoSuchKeyFound
295+ }
296+
297+ pairs := make (map [string ]string )
298+ err = realToPseudoBucket .ForEach (func (r , p []byte ) error {
299+ pairs [string (r )] = string (p )
300+
301+ return nil
302+ })
303+ if err != nil {
304+ return nil , err
305+ }
306+
307+ return NewPrivacyMapPairs (pairs ), nil
308+ }
309+
257310func HideString (tx PrivacyMapTx , real string ) (string , error ) {
258311 pseudo , err := tx .RealToPseudo (real )
259312 if err != nil && err != ErrNoSuchKeyFound {
@@ -460,3 +513,73 @@ func decodeChannelPoint(cp string) (string, uint32, error) {
460513
461514 return parts [0 ], uint32 (index ), nil
462515}
516+
517+ // PrivacyMapReader is an interface that gives read access to a privacy map
518+ // DB.
519+ type PrivacyMapReader interface {
520+ // GetPseudo returns the associated pseudo value for a given real value.
521+ // If no such real value exists in the DB, then false is returned.
522+ GetPseudo (real string ) (string , bool )
523+ }
524+
525+ // PrivacyMapPairs is an in memory implementation of the PrivacyMapReader.
526+ type PrivacyMapPairs struct {
527+ // pairs is a map from real to psuedo strings.
528+ pairs map [string ]string
529+
530+ mu sync.Mutex
531+ }
532+
533+ // NewPrivacyMapPairs constructs a new PrivacyMapPairs struct. It may be
534+ // initialised with either a nil map or a pre-defined real-to-pseudo strings
535+ // map.
536+ func NewPrivacyMapPairs (m map [string ]string ) * PrivacyMapPairs {
537+ if m != nil {
538+ return & PrivacyMapPairs {
539+ pairs : m ,
540+ }
541+ }
542+
543+ return & PrivacyMapPairs {
544+ pairs : make (map [string ]string ),
545+ }
546+ }
547+
548+ // GetPseudo returns the associated pseudo value for a given real value. If no
549+ // such real value exists in the DB, then false is returned.
550+ //
551+ // NOTE: this is part of the PrivacyMapReader interface.
552+ func (p * PrivacyMapPairs ) GetPseudo (real string ) (string , bool ) {
553+ p .mu .Lock ()
554+ defer p .mu .Unlock ()
555+
556+ pseudo , ok := p .pairs [real ]
557+
558+ return pseudo , ok
559+ }
560+
561+ // Add adds the passed set of real-to-pseudo pairs to the PrivacyMapPairs
562+ // structure. It will throw an error if the new pairs conflict with any of the
563+ // existing pairs.
564+ func (p * PrivacyMapPairs ) Add (pairs map [string ]string ) error {
565+ p .mu .Lock ()
566+ defer p .mu .Unlock ()
567+
568+ // Do a first pass to ensure that none of the new entries conflict with
569+ // the existing entries. We do this so that we don't mutate the set of
570+ // pairs before we know that the new set is valid.
571+ for realStr , pseudoStr := range pairs {
572+ ps , ok := p .pairs [realStr ]
573+ if ok && ps != pseudoStr {
574+ return fmt .Errorf ("cannot replace existing pseudo " +
575+ "entry for real value: %s" , realStr )
576+ }
577+ }
578+
579+ // In our second pass, we can add the new pairs to our set.
580+ for realStr , pseudoStr := range pairs {
581+ p .pairs [realStr ] = pseudoStr
582+ }
583+
584+ return nil
585+ }
0 commit comments