github.com/ethersphere/bee/v2@v2.2.0/pkg/addressbook/addressbook.go (about)

     1  // Copyright 2020 The Swarm Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package addressbook
     6  
     7  import (
     8  	"errors"
     9  	"fmt"
    10  	"strings"
    11  
    12  	"github.com/ethersphere/bee/v2/pkg/bzz"
    13  	"github.com/ethersphere/bee/v2/pkg/storage"
    14  	"github.com/ethersphere/bee/v2/pkg/swarm"
    15  )
    16  
    17  const keyPrefix = "addressbook_entry_"
    18  
    19  var _ Interface = (*store)(nil)
    20  
    21  var ErrNotFound = errors.New("addressbook: not found")
    22  
    23  // Interface is the AddressBook interface.
    24  type Interface interface {
    25  	GetPutter
    26  	Remover
    27  	// Overlays returns a list of all overlay addresses saved in addressbook.
    28  	Overlays() ([]swarm.Address, error)
    29  	// IterateOverlays exposes overlays in a form of an iterator.
    30  	IterateOverlays(func(swarm.Address) (bool, error)) error
    31  	// Addresses returns a list of all bzz.Address-es saved in addressbook.
    32  	Addresses() ([]bzz.Address, error)
    33  }
    34  
    35  type GetPutter interface {
    36  	Getter
    37  	Putter
    38  }
    39  
    40  type Getter interface {
    41  	// Get returns pointer to saved bzz.Address for requested overlay address.
    42  	Get(overlay swarm.Address) (addr *bzz.Address, err error)
    43  }
    44  
    45  type Putter interface {
    46  	// Put saves relation between peer overlay address and bzz.Address address.
    47  	Put(overlay swarm.Address, addr bzz.Address) (err error)
    48  }
    49  
    50  type Remover interface {
    51  	// Remove removes overlay address.
    52  	Remove(overlay swarm.Address) error
    53  }
    54  
    55  type store struct {
    56  	store storage.StateStorer
    57  }
    58  
    59  // New creates new addressbook for state storer.
    60  func New(storer storage.StateStorer) Interface {
    61  	return &store{
    62  		store: storer,
    63  	}
    64  }
    65  
    66  func (s *store) Get(overlay swarm.Address) (*bzz.Address, error) {
    67  	key := keyPrefix + overlay.String()
    68  	v := &bzz.Address{}
    69  	err := s.store.Get(key, &v)
    70  	if err != nil {
    71  		if errors.Is(err, storage.ErrNotFound) {
    72  			return nil, ErrNotFound
    73  		}
    74  
    75  		return nil, err
    76  	}
    77  	return v, nil
    78  }
    79  
    80  func (s *store) Put(overlay swarm.Address, addr bzz.Address) (err error) {
    81  	key := keyPrefix + overlay.String()
    82  	return s.store.Put(key, &addr)
    83  }
    84  
    85  func (s *store) Remove(overlay swarm.Address) error {
    86  	return s.store.Delete(keyPrefix + overlay.String())
    87  }
    88  
    89  func (s *store) IterateOverlays(cb func(swarm.Address) (bool, error)) error {
    90  	return s.store.Iterate(keyPrefix, func(key, _ []byte) (stop bool, err error) {
    91  		k := string(key)
    92  		if !strings.HasPrefix(k, keyPrefix) {
    93  			return true, nil
    94  		}
    95  		split := strings.SplitAfter(k, keyPrefix)
    96  		if len(split) != 2 {
    97  			return true, fmt.Errorf("invalid overlay key: %s", k)
    98  		}
    99  		addr, err := swarm.ParseHexAddress(split[1])
   100  		if err != nil {
   101  			return true, err
   102  		}
   103  		stop, err = cb(addr)
   104  		if err != nil {
   105  			return true, err
   106  		}
   107  		if stop {
   108  			return true, nil
   109  		}
   110  		return false, nil
   111  	})
   112  }
   113  
   114  func (s *store) Overlays() (overlays []swarm.Address, err error) {
   115  	err = s.IterateOverlays(func(addr swarm.Address) (stop bool, err error) {
   116  		overlays = append(overlays, addr)
   117  		return false, nil
   118  	})
   119  	if err != nil {
   120  		return nil, err
   121  	}
   122  
   123  	return overlays, nil
   124  }
   125  
   126  func (s *store) Addresses() (addresses []bzz.Address, err error) {
   127  	err = s.store.Iterate(keyPrefix, func(_, value []byte) (stop bool, err error) {
   128  		entry := &bzz.Address{}
   129  		err = entry.UnmarshalJSON(value)
   130  		if err != nil {
   131  			return true, err
   132  		}
   133  
   134  		addresses = append(addresses, *entry)
   135  		return false, nil
   136  	})
   137  	if err != nil {
   138  		return nil, err
   139  	}
   140  
   141  	return addresses, nil
   142  }