mirror of
https://github.com/lightninglabs/lightning-terminal.git
synced 2026-08-13 12:33:36 +02:00
firewalldb: add FetchAllPairs to PrivacyMapTx interface
This commit adds a new FetchAllPairs to the PrivacyMapTx interface. This method returns a new PrivacyMapPairs struct which is an in-memory privacy map DB. The PrivacyMapPairs struct implements a new PrivacyMapReader interface which can be used to pass around read only access to the PrivacyMapPairs struct.
This commit is contained in:
parent
9b7ed4a4d9
commit
d0bc3c37f1
3 changed files with 204 additions and 0 deletions
|
|
@ -555,6 +555,12 @@ func (m *mockPrivacyMapDB) RealToPseudo(real string) (string, error) {
|
|||
return p, nil
|
||||
}
|
||||
|
||||
func (m *mockPrivacyMapDB) FetchAllPairs() (*firewalldb.PrivacyMapPairs,
|
||||
error) {
|
||||
|
||||
return firewalldb.NewPrivacyMapPairs(m.r2p), nil
|
||||
}
|
||||
|
||||
var _ firewalldb.PrivacyMapDB = (*mockPrivacyMapDB)(nil)
|
||||
|
||||
// TestRandBetween tests random number generation for numbers in an interval.
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import (
|
|||
"math/big"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/lightninglabs/lightning-terminal/session"
|
||||
"go.etcd.io/bbolt"
|
||||
|
|
@ -78,6 +79,10 @@ type PrivacyMapTx interface {
|
|||
// RealToPseudo returns the pseudo value associated with the given real
|
||||
// value. If no such pair is found, then ErrNoSuchKeyFound is returned.
|
||||
RealToPseudo(real string) (string, error)
|
||||
|
||||
// FetchAllPairs loads and returns the real-to-pseudo pairs in the form
|
||||
// of a PrivacyMapPairs struct.
|
||||
FetchAllPairs() (*PrivacyMapPairs, error)
|
||||
}
|
||||
|
||||
// privacyMapDB is an implementation of PrivacyMapDB.
|
||||
|
|
@ -169,6 +174,8 @@ type privacyMapTx struct {
|
|||
}
|
||||
|
||||
// NewPair inserts a new real-pseudo pair into the db.
|
||||
//
|
||||
// NOTE: this is part of the PrivacyMapTx interface.
|
||||
func (p *privacyMapTx) NewPair(real, pseudo string) error {
|
||||
privacyBucket, err := getBucket(p.boltTx, privacyBucketKey)
|
||||
if err != nil {
|
||||
|
|
@ -214,6 +221,8 @@ func (p *privacyMapTx) NewPair(real, pseudo string) error {
|
|||
|
||||
// PseudoToReal will check the db to see if the given pseudo key exists. If
|
||||
// it does then the real value is returned, else an error is returned.
|
||||
//
|
||||
// NOTE: this is part of the PrivacyMapTx interface.
|
||||
func (p *privacyMapTx) PseudoToReal(pseudo string) (string, error) {
|
||||
privacyBucket, err := getBucket(p.boltTx, privacyBucketKey)
|
||||
if err != nil {
|
||||
|
|
@ -240,6 +249,8 @@ func (p *privacyMapTx) PseudoToReal(pseudo string) (string, error) {
|
|||
|
||||
// RealToPseudo will check the db to see if the given real key exists. If
|
||||
// it does then the pseudo value is returned, else an error is returned.
|
||||
//
|
||||
// NOTE: this is part of the PrivacyMapTx interface.
|
||||
func (p *privacyMapTx) RealToPseudo(real string) (string, error) {
|
||||
privacyBucket, err := getBucket(p.boltTx, privacyBucketKey)
|
||||
if err != nil {
|
||||
|
|
@ -264,6 +275,38 @@ func (p *privacyMapTx) RealToPseudo(real string) (string, error) {
|
|||
return string(pseudo), nil
|
||||
}
|
||||
|
||||
// FetchAllPairs loads and returns the real-to-pseudo pairs.
|
||||
//
|
||||
// NOTE: this is part of the PrivacyMapTx interface.
|
||||
func (p *privacyMapTx) FetchAllPairs() (*PrivacyMapPairs, error) {
|
||||
privacyBucket, err := getBucket(p.boltTx, privacyBucketKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sessBucket := privacyBucket.Bucket(p.groupID[:])
|
||||
if sessBucket == nil {
|
||||
return nil, ErrNoSuchKeyFound
|
||||
}
|
||||
|
||||
realToPseudoBucket := sessBucket.Bucket(realToPseudoKey)
|
||||
if realToPseudoBucket == nil {
|
||||
return nil, ErrNoSuchKeyFound
|
||||
}
|
||||
|
||||
pairs := make(map[string]string)
|
||||
err = realToPseudoBucket.ForEach(func(r, p []byte) error {
|
||||
pairs[string(r)] = string(p)
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewPrivacyMapPairs(pairs), nil
|
||||
}
|
||||
|
||||
func HideString(tx PrivacyMapTx, real string) (string, error) {
|
||||
pseudo, err := tx.RealToPseudo(real)
|
||||
if err != nil && err != ErrNoSuchKeyFound {
|
||||
|
|
@ -470,3 +513,73 @@ func decodeChannelPoint(cp string) (string, uint32, error) {
|
|||
|
||||
return parts[0], uint32(index), nil
|
||||
}
|
||||
|
||||
// PrivacyMapReader is an interface that gives read access to a privacy map
|
||||
// DB.
|
||||
type PrivacyMapReader interface {
|
||||
// GetPseudo returns the associated pseudo value for a given real value.
|
||||
// If no such real value exists in the DB, then false is returned.
|
||||
GetPseudo(real string) (string, bool)
|
||||
}
|
||||
|
||||
// PrivacyMapPairs is an in memory implementation of the PrivacyMapReader.
|
||||
type PrivacyMapPairs struct {
|
||||
// pairs is a map from real to psuedo strings.
|
||||
pairs map[string]string
|
||||
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
// NewPrivacyMapPairs constructs a new PrivacyMapPairs struct. It may be
|
||||
// initialised with either a nil map or a pre-defined real-to-pseudo strings
|
||||
// map.
|
||||
func NewPrivacyMapPairs(m map[string]string) *PrivacyMapPairs {
|
||||
if m != nil {
|
||||
return &PrivacyMapPairs{
|
||||
pairs: m,
|
||||
}
|
||||
}
|
||||
|
||||
return &PrivacyMapPairs{
|
||||
pairs: make(map[string]string),
|
||||
}
|
||||
}
|
||||
|
||||
// GetPseudo returns the associated pseudo value for a given real value. If no
|
||||
// such real value exists in the DB, then false is returned.
|
||||
//
|
||||
// NOTE: this is part of the PrivacyMapReader interface.
|
||||
func (p *PrivacyMapPairs) GetPseudo(real string) (string, bool) {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
|
||||
pseudo, ok := p.pairs[real]
|
||||
|
||||
return pseudo, ok
|
||||
}
|
||||
|
||||
// Add adds the passed set of real-to-pseudo pairs to the PrivacyMapPairs
|
||||
// structure. It will throw an error if the new pairs conflict with any of the
|
||||
// existing pairs.
|
||||
func (p *PrivacyMapPairs) Add(pairs map[string]string) error {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
|
||||
// Do a first pass to ensure that none of the new entries conflict with
|
||||
// the existing entries. We do this so that we don't mutate the set of
|
||||
// pairs before we know that the new set is valid.
|
||||
for realStr, pseudoStr := range pairs {
|
||||
ps, ok := p.pairs[realStr]
|
||||
if ok && ps != pseudoStr {
|
||||
return fmt.Errorf("cannot replace existing pseudo "+
|
||||
"entry for real value: %s", realStr)
|
||||
}
|
||||
}
|
||||
|
||||
// In our second pass, we can add the new pairs to our set.
|
||||
for realStr, pseudoStr := range pairs {
|
||||
p.pairs[realStr] = pseudoStr
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,13 @@ func TestPrivacyMapStorage(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
require.Equal(t, "real", real)
|
||||
|
||||
pairs, err := tx.FetchAllPairs()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.EqualValues(t, pairs.pairs, map[string]string{
|
||||
"real": "pseudo",
|
||||
})
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
|
|
@ -59,6 +66,13 @@ func TestPrivacyMapStorage(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
require.Equal(t, "real 2", real)
|
||||
|
||||
pairs, err := tx.FetchAllPairs()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.EqualValues(t, pairs.pairs, map[string]string{
|
||||
"real 2": "pseudo 2",
|
||||
})
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
|
|
@ -81,6 +95,77 @@ func TestPrivacyMapStorage(t *testing.T) {
|
|||
require.ErrorContains(t, err, "an entry already exists for "+
|
||||
"pseudo value")
|
||||
|
||||
// Add a few more pairs.
|
||||
err = tx.NewPair("real 2", "pseudo 2")
|
||||
require.NoError(t, err)
|
||||
|
||||
err = tx.NewPair("real 3", "pseudo 3")
|
||||
require.NoError(t, err)
|
||||
|
||||
err = tx.NewPair("real 4", "pseudo 4")
|
||||
require.NoError(t, err)
|
||||
|
||||
// Check that FetchAllPairs correctly returns all the pairs.
|
||||
pairs, err := tx.FetchAllPairs()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.EqualValues(t, pairs.pairs, map[string]string{
|
||||
"real 1": "pseudo 1",
|
||||
"real 2": "pseudo 2",
|
||||
"real 3": "pseudo 3",
|
||||
"real 4": "pseudo 4",
|
||||
})
|
||||
|
||||
// Do a few tests to ensure that the PrivacyMapPairs struct
|
||||
// returned from FetchAllPairs also works as expected.
|
||||
pseudo, ok := pairs.GetPseudo("real 1")
|
||||
require.True(t, ok)
|
||||
require.Equal(t, "pseudo 1", pseudo)
|
||||
|
||||
// Fetch a real value that is not present.
|
||||
_, ok = pairs.GetPseudo("real 5")
|
||||
require.False(t, ok)
|
||||
|
||||
// Try to add a conflicting pair.
|
||||
err = pairs.Add(map[string]string{"real 2": "pseudo 10"})
|
||||
require.ErrorContains(t, err, "cannot replace existing "+
|
||||
"pseudo entry for real value")
|
||||
|
||||
// Add a new pair.
|
||||
err = pairs.Add(map[string]string{"real 5": "pseudo 5"})
|
||||
require.NoError(t, err)
|
||||
|
||||
pseudo, ok = pairs.GetPseudo("real 5")
|
||||
require.True(t, ok)
|
||||
require.Equal(t, "pseudo 5", pseudo)
|
||||
|
||||
// Finally, also test adding multiple new pairs with some
|
||||
// overlapping with previously added pairs.
|
||||
err = pairs.Add(map[string]string{
|
||||
// Add some pairs that already exist.
|
||||
"real 1": "pseudo 1",
|
||||
"real 3": "pseudo 3",
|
||||
// Add some new pairs.
|
||||
"real 6": "pseudo 6",
|
||||
"real 7": "pseudo 7",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify that all the expected pairs can be found.
|
||||
for r, p := range map[string]string{
|
||||
"real 1": "pseudo 1",
|
||||
"real 2": "pseudo 2",
|
||||
"real 3": "pseudo 3",
|
||||
"real 4": "pseudo 4",
|
||||
"real 5": "pseudo 5",
|
||||
"real 6": "pseudo 6",
|
||||
"real 7": "pseudo 7",
|
||||
} {
|
||||
pseudo, ok = pairs.GetPseudo(r)
|
||||
require.True(t, ok)
|
||||
require.Equal(t, p, pseudo)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue