Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 0 additions & 15 deletions pkg/bzz/address.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (
"encoding/json"
"errors"
"fmt"
"slices"

"github.com/ethereum/go-ethereum/common"
"github.com/ethersphere/bee/v2/pkg/crypto"
Expand All @@ -38,7 +37,6 @@ type Address struct {

type addressJSON struct {
Overlay string `json:"overlay"`
Underlay string `json:"underlay"` // For backward compatibility
Underlays []string `json:"underlays"`
Signature string `json:"signature"`
Nonce string `json:"transaction"`
Expand Down Expand Up @@ -145,16 +143,8 @@ func (a *Address) MarshalJSON() ([]byte, error) {
if len(a.Underlays) == 0 {
return nil, fmt.Errorf("no underlays for %s", a.Overlay)
}

// select the underlay address for backward compatibility
var underlay string
if v := SelectBestAdvertisedAddress(a.Underlays, nil); v != nil {
underlay = v.String()
}

return json.Marshal(&addressJSON{
Overlay: a.Overlay.String(),
Underlay: underlay,
Underlays: a.underlaysAsStrings(),
Signature: base64.StdEncoding.EncodeToString(a.Signature),
Nonce: common.Bytes2Hex(a.Nonce),
Expand All @@ -175,11 +165,6 @@ func (a *Address) UnmarshalJSON(b []byte) error {

a.Overlay = addr

// append the underlay for backward compatibility
if !slices.Contains(v.Underlays, v.Underlay) {
v.Underlays = append(v.Underlays, v.Underlay)
}

multiaddrs, err := parseMultiaddrs(v.Underlays)
if err != nil {
return err
Expand Down
2 changes: 1 addition & 1 deletion pkg/bzz/address_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func TestBzzAddress(t *testing.T) {
t.Fatal(err)
}

bzzAddress2, err := bzz.ParseAddress(node1ma.Bytes(), overlay.Bytes(), bzzAddress.Signature, nonce, true, 3)
bzzAddress2, err := bzz.ParseAddress(bzz.SerializeUnderlays([]multiaddr.Multiaddr{node1ma}), overlay.Bytes(), bzzAddress.Signature, nonce, true, 3)
if err != nil {
t.Fatal(err)
}
Expand Down
7 changes: 0 additions & 7 deletions pkg/bzz/export_test.go

This file was deleted.

39 changes: 4 additions & 35 deletions pkg/bzz/underlay.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,16 @@ package bzz

import (
"bytes"
"errors"
"fmt"

"github.com/multiformats/go-multiaddr"
"github.com/multiformats/go-varint"
)

// underlayListPrefix is a magic byte designated for identifying a serialized list of multiaddrs.
// A value of 0x99 (153) was chosen as it is not a defined multiaddr protocol code.
// This ensures that a failure is triggered by the original multiaddr.NewMultiaddrBytes function,
// which expects a valid protocol code at the start of the data.
const underlayListPrefix byte = 0x99

// SerializeUnderlays serializes a slice of multiaddrs into a single byte slice.
// If the slice contains exactly one address, the standard, backward-compatible
// multiaddr format is used. For zero or more than one address, a custom list format
// prefixed with a magic byte is utilized.
func SerializeUnderlays(addrs []multiaddr.Multiaddr) []byte {
// Backward compatibility if exactly one address is present.
if len(addrs) == 1 {
return addrs[0].Bytes()
}

// For 0 or 2+ addresses, the custom list format with the prefix is used.
// The format is: [prefix_byte][varint_len_1][addr_1_bytes]...
// The format is: [varint_len_1][addr_1_bytes]...
var buf bytes.Buffer
buf.WriteByte(underlayListPrefix)

for _, addr := range addrs {
addrBytes := addr.Bytes()
Expand All @@ -43,29 +26,15 @@ func SerializeUnderlays(addrs []multiaddr.Multiaddr) []byte {
}

// DeserializeUnderlays deserializes a byte slice into a slice of multiaddrs.
// The data format is automatically detected as either a single legacy multiaddr
// or a list of multiaddrs (identified by underlayListPrefix), and is parsed accordingly.
func DeserializeUnderlays(data []byte) ([]multiaddr.Multiaddr, error) {
if len(data) == 0 {
return nil, errors.New("cannot deserialize empty byte slice")
return nil, nil
}

// If the data begins with the magic prefix, it is handled as a list.
if data[0] == underlayListPrefix {
return deserializeList(data[1:])
}

// Otherwise, the data is handled as a single, backward-compatible multiaddr.
addr, err := multiaddr.NewMultiaddrBytes(data)
if err != nil {
return nil, fmt.Errorf("failed to parse as single multiaddr: %w", err)
}
// The result is returned as a single-element slice for a consistent return type.
return []multiaddr.Multiaddr{addr}, nil
return deserializeList(data)
}

// deserializeList handles the parsing of the custom list format.
// The provided data is expected to have already been stripped of the underlayListPrefix.
// deserializeList handles the parsing of the underlays list format.
func deserializeList(data []byte) ([]multiaddr.Multiaddr, error) {
var addrs []multiaddr.Multiaddr
r := bytes.NewReader(data)
Expand Down
87 changes: 9 additions & 78 deletions pkg/bzz/underlay_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,28 +24,15 @@ func TestSerializeUnderlays(t *testing.T) {
addrs := []multiaddr.Multiaddr{ip4TCPAddr, p2pAddr, wssAddr, dnsSwarmAddr}
serialized := bzz.SerializeUnderlays(addrs)

if serialized[0] != bzz.UnderlayListPrefix {
t.Errorf("expected prefix %x for multiple addresses, got %x", bzz.UnderlayListPrefix, serialized[0])
}
})

t.Run("single address list", func(t *testing.T) {
addrs := []multiaddr.Multiaddr{dnsSwarmAddr}
serialized := bzz.SerializeUnderlays(addrs)
expected := dnsSwarmAddr.Bytes() // Should be legacy format without prefix

if !bytes.Equal(serialized, expected) {
t.Errorf("expected single address to serialize to legacy format %x, got %x", expected, serialized)
}
if serialized[0] == bzz.UnderlayListPrefix {
t.Error("single address serialization should not have the list prefix")
if len(serialized) == 0 {
t.Error("expected serialized bytes for non-empty list")
}
})

t.Run("empty list", func(t *testing.T) {
addrs := []multiaddr.Multiaddr{}
serialized := bzz.SerializeUnderlays(addrs)
expected := []byte{bzz.UnderlayListPrefix}
expected := []byte{}
if !bytes.Equal(serialized, expected) {
t.Errorf("expected %x for empty list, got %x", expected, serialized)
}
Expand All @@ -54,7 +41,7 @@ func TestSerializeUnderlays(t *testing.T) {
t.Run("nil list", func(t *testing.T) {
var addrs []multiaddr.Multiaddr = nil
serialized := bzz.SerializeUnderlays(addrs)
expected := []byte{bzz.UnderlayListPrefix}
expected := []byte{}
if !bytes.Equal(serialized, expected) {
t.Errorf("expected %x for nil list, got %x", expected, serialized)
}
Expand All @@ -78,26 +65,8 @@ func TestDeserializeUnderlays(t *testing.T) {
}
})

t.Run("single legacy multiaddr", func(t *testing.T) {
singleBytes := wssAddr.Bytes()
deserialized, err := bzz.DeserializeUnderlays(singleBytes)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if len(deserialized) != 1 || !deserialized[0].Equal(wssAddr) {
t.Errorf("expected [%v], got %v", wssAddr, deserialized)
}
})

t.Run("empty byte slice", func(t *testing.T) {
_, err := bzz.DeserializeUnderlays([]byte{})
if err == nil {
t.Error("expected an error for empty slice, but got nil")
}
})

t.Run("list with only prefix", func(t *testing.T) {
deserialized, err := bzz.DeserializeUnderlays([]byte{bzz.UnderlayListPrefix})
deserialized, err := bzz.DeserializeUnderlays([]byte{})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
Expand All @@ -109,8 +78,8 @@ func TestDeserializeUnderlays(t *testing.T) {
t.Run("serialize deserialize empty list", func(t *testing.T) {
addrs := []multiaddr.Multiaddr{}
serialized := bzz.SerializeUnderlays(addrs)
if !bytes.Equal(serialized, []byte{bzz.UnderlayListPrefix}) {
t.Errorf("expected %v, got %v", []byte{bzz.UnderlayListPrefix}, serialized)
if !bytes.Equal(serialized, []byte{}) {
t.Errorf("expected %v, got %v", []byte{}, serialized)
}
deserialized, err := bzz.DeserializeUnderlays(serialized)
if err != nil {
Expand All @@ -123,8 +92,8 @@ func TestDeserializeUnderlays(t *testing.T) {

t.Run("serialize deserialize nil list", func(t *testing.T) {
serialized := bzz.SerializeUnderlays(nil)
if !bytes.Equal(serialized, []byte{bzz.UnderlayListPrefix}) {
t.Errorf("expected %v, got %v", []byte{bzz.UnderlayListPrefix}, serialized)
if !bytes.Equal(serialized, []byte{}) {
t.Errorf("expected %v, got %v", []byte{}, serialized)
}
deserialized, err := bzz.DeserializeUnderlays(serialized)
if err != nil {
Expand All @@ -138,7 +107,6 @@ func TestDeserializeUnderlays(t *testing.T) {
t.Run("corrupted list - length too long", func(t *testing.T) {
maBytes := ip4TCPAddr.Bytes()
var buf bytes.Buffer
buf.WriteByte(bzz.UnderlayListPrefix)
buf.Write(varint.ToUvarint(uint64(len(maBytes) + 5))) // Write a length that is too long
buf.Write(maBytes)

Expand All @@ -151,7 +119,6 @@ func TestDeserializeUnderlays(t *testing.T) {
t.Run("corrupted list - invalid multiaddr bytes", func(t *testing.T) {
invalidAddrBytes := []byte{0xde, 0xad, 0xbe, 0xef}
var buf bytes.Buffer
buf.WriteByte(bzz.UnderlayListPrefix)
buf.Write(varint.ToUvarint(uint64(len(invalidAddrBytes))))
buf.Write(invalidAddrBytes)

Expand Down Expand Up @@ -205,42 +172,6 @@ func TestSerializeUnderlaysDeserializeUnderlays(t *testing.T) {
})
}

func TestLegacyCompatibility(t *testing.T) {
ip4TCPAddr := mustNewMultiaddr(t, "/ip4/1.2.3.4/tcp/5678/p2p/QmWqeeHEqG2db37JsuKUxyJ2JF8LtVJMGohKVT8h3aeCVH")
p2pAddr := mustNewMultiaddr(t, "/ip4/65.108.66.216/tcp/16341/p2p/QmVuCJ3M96c7vwv4MQBv7WY1HWQacyCEHvM99R8MUDj95d")
dnsSwarmAddr := mustNewMultiaddr(t, "/dnsaddr/mainnet.ethswarm.org")

t.Run("legacy parser fails on new list format", func(t *testing.T) {
addrs := []multiaddr.Multiaddr{ip4TCPAddr, p2pAddr, dnsSwarmAddr}
listBytes := bzz.SerializeUnderlays(addrs) // This will have the prefix
_, err := multiaddr.NewMultiaddrBytes(listBytes)
if err == nil {
t.Error("expected legacy NewMultiaddrBytes to fail on list format, but it succeeded")
}
})

t.Run("legacy parser succeeds on new single-addr format", func(t *testing.T) {
addrs := []multiaddr.Multiaddr{dnsSwarmAddr}
singleBytes := bzz.SerializeUnderlays(addrs) // This will NOT have the prefix
_, err := multiaddr.NewMultiaddrBytes(singleBytes)
if err != nil {
t.Errorf("expected legacy NewMultiaddrBytes to succeed on single-addr format, but it failed: %v", err)
}
})

t.Run("new parser succeeds on legacy format", func(t *testing.T) {
singleBytes := p2pAddr.Bytes()
deserialized, err := bzz.DeserializeUnderlays(singleBytes)
if err != nil {
t.Fatalf("Deserialize failed on legacy bytes: %v", err)
}
expected := []multiaddr.Multiaddr{p2pAddr}
if !reflect.DeepEqual(expected, deserialized) {
t.Errorf("expected %v, got %v", expected, deserialized)
}
})
}

func mustNewMultiaddr(tb testing.TB, s string) multiaddr.Multiaddr {
tb.Helper()

Expand Down
6 changes: 2 additions & 4 deletions pkg/hive/hive.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ var (
)

type Service struct {
streamer p2p.Bee260CompatibilityStreamer
streamer p2p.Streamer
addressBook addressbook.GetPutter
addPeersHandler func(...swarm.Address)
networkID uint64
Expand All @@ -67,7 +67,7 @@ type Service struct {
overlay swarm.Address
}

func New(streamer p2p.Bee260CompatibilityStreamer, addressbook addressbook.GetPutter, networkID uint64, bootnode bool, allowPrivateCIDRs bool, overlay swarm.Address, logger log.Logger) *Service {
func New(streamer p2p.Streamer, addressbook addressbook.GetPutter, networkID uint64, bootnode bool, allowPrivateCIDRs bool, overlay swarm.Address, logger log.Logger) *Service {
svc := &Service{
streamer: streamer,
logger: logger.WithName(loggerName).Register(),
Expand Down Expand Up @@ -196,8 +196,6 @@ func (s *Service) sendPeers(ctx context.Context, peer swarm.Address, peers []swa
continue
}

advertisableUnderlays = p2p.FilterBee260CompatibleUnderlays(s.streamer.IsBee260(peer), advertisableUnderlays)

peersRequest.Peers = append(peersRequest.Peers, &pb.BzzAddress{
Overlay: addr.Overlay.Bytes(),
Underlay: bzz.SerializeUnderlays(advertisableUnderlays),
Expand Down
Loading
Loading