Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
eebec22
chore: remove legacy code
sbackend123 Mar 25, 2026
af6c38e
chore: remove legacy code for underlay addresses
sbackend123 Mar 30, 2026
71d07fd
chore: noop old migrations and remove legacy underlay test
sbackend123 Mar 30, 2026
2ee43af
chore: remove underlayListPrefix prefix
sbackend123 Mar 31, 2026
68613ec
fix: restore underlay prefix and tests for backward compatibility wit…
sbackend123 Apr 1, 2026
47166e4
Merge branch 'master' into chore/remove-backwards-compatibility-with-…
sbackend123 Apr 22, 2026
fff123b
Merge branch 'refs/heads/master' into chore/remove-backwards-compatib…
sbackend123 Apr 22, 2026
8a068fc
fix: remove empty files
sbackend123 Apr 22, 2026
70022f4
fix: remove legacy migrations files
sbackend123 Apr 22, 2026
5ac22ee
fix: fix broken merge
sbackend123 Apr 22, 2026
1e92169
fix: remove unnecessary changes
sbackend123 Apr 26, 2026
c9674df
fix: revert unnecessary changes
sbackend123 Apr 26, 2026
4758020
fix: revert unnecessary changes 3
sbackend123 Apr 27, 2026
08386b3
fix: return comments
sbackend123 Apr 27, 2026
e0ce20d
fix: clean up
sbackend123 Apr 28, 2026
7adc040
fix: remove single underlay address complitely
sbackend123 Apr 30, 2026
90459ba
fix: added comment
sbackend123 Apr 30, 2026
2a663ab
fix: cleanup
sbackend123 Apr 30, 2026
3058490
Merge branch 'master' into chore/remove-backwards-compatibility-with-…
sbackend123 Jun 1, 2026
5480ccf
fix: merge with master and fix merge
sbackend123 Jun 1, 2026
e5995f7
fix: fix unit tests
sbackend123 Jun 1, 2026
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
12 changes: 0 additions & 12 deletions pkg/bzz/underlay.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,7 @@ import (
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]...
var buf bytes.Buffer
Expand All @@ -43,14 +35,10 @@ 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")
}

// If the data begins with the magic prefix, it is handled as a list.
if data[0] == underlayListPrefix {
return deserializeList(data[1:])
}
Expand Down
60 changes: 0 additions & 60 deletions pkg/bzz/underlay_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,6 @@ func TestSerializeUnderlays(t *testing.T) {
}
})

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")
}
})

t.Run("empty list", func(t *testing.T) {
addrs := []multiaddr.Multiaddr{}
serialized := bzz.SerializeUnderlays(addrs)
Expand Down Expand Up @@ -78,17 +65,6 @@ 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 {
Expand Down Expand Up @@ -205,42 +181,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
64 changes: 29 additions & 35 deletions pkg/p2p/libp2p/internal/handshake/handshake.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,20 +67,6 @@ type Addresser interface {
AdvertizableAddrs() ([]ma.Multiaddr, error)
}

type Option struct {
bee260compatibility bool
}

// WithBee260Compatibility option ensures that only one underlay address is
// passed to the peer in p2p protocol messages, so that nodes with version 2.6.0
// and older can deserialize it. This option can be safely removed when bee
// version 2.6.0 is deprecated.
func WithBee260Compatibility(yes bool) func(*Option) {
return func(o *Option) {
o.bee260compatibility = yes
}
}

// Service can perform initiate or handle a handshake between peers.
type Service struct {
signer crypto.Signer
Expand Down Expand Up @@ -144,23 +130,18 @@ func (s *Service) SetPicker(n p2p.Picker) {
}

// Handshake initiates a handshake with a peer.
func (s *Service) Handshake(ctx context.Context, stream p2p.Stream, peerMultiaddrs []ma.Multiaddr, opts ...func(*Option)) (i *Info, err error) {
func (s *Service) Handshake(ctx context.Context, stream p2p.Stream, peerMultiaddrs []ma.Multiaddr) (i *Info, err error) {
loggerV1 := s.logger.V(1).Register()

o := new(Option)
for _, set := range opts {
set(o)
}

ctx, cancel := context.WithTimeout(ctx, handshakeTimeout)
defer cancel()

w, r := protobuf.NewWriterAndReader(stream)

peerMultiaddrs = p2p.FilterBee260CompatibleUnderlays(o.bee260compatibility, peerMultiaddrs)
synUnderlay := bzz.SerializeUnderlays(peerMultiaddrs)
s.logger.Debug("handshake outbound syn underlay", "payload_len", len(synUnderlay), "first_byte", firstByteString(synUnderlay), "payload_prefix", payloadPrefix(synUnderlay))

if err := w.WriteMsgWithContext(ctx, &pb.Syn{
ObservedUnderlay: bzz.SerializeUnderlays(peerMultiaddrs),
ObservedUnderlay: synUnderlay,
}); err != nil {
return nil, fmt.Errorf("write syn message: %w", err)
}
Expand All @@ -172,6 +153,7 @@ func (s *Service) Handshake(ctx context.Context, stream p2p.Stream, peerMultiadd

observedUnderlays, err := bzz.DeserializeUnderlays(resp.Syn.ObservedUnderlay)
if err != nil {
s.logger.Debug("handshake invalid synack observed underlay payload", "payload_len", len(resp.Syn.ObservedUnderlay), "first_byte", firstByteString(resp.Syn.ObservedUnderlay), "payload_prefix", payloadPrefix(resp.Syn.ObservedUnderlay), "error", err)
return nil, ErrInvalidSyn
}

Expand Down Expand Up @@ -212,8 +194,6 @@ func (s *Service) Handshake(ctx context.Context, stream p2p.Stream, peerMultiadd
return a.Equal(b)
})

advertisableUnderlays = p2p.FilterBee260CompatibleUnderlays(o.bee260compatibility, advertisableUnderlays)

bzzAddress, err := bzz.NewAddress(s.signer, advertisableUnderlays, s.overlay, s.networkID, s.nonce)
if err != nil {
return nil, err
Expand Down Expand Up @@ -258,14 +238,9 @@ func (s *Service) Handshake(ctx context.Context, stream p2p.Stream, peerMultiadd
}

// Handle handles an incoming handshake from a peer.
func (s *Service) Handle(ctx context.Context, stream p2p.Stream, peerMultiaddrs []ma.Multiaddr, opts ...func(*Option)) (i *Info, err error) {
func (s *Service) Handle(ctx context.Context, stream p2p.Stream, peerMultiaddrs []ma.Multiaddr) (i *Info, err error) {
loggerV1 := s.logger.V(1).Register()

o := new(Option)
for _, set := range opts {
set(o)
}

ctx, cancel := context.WithTimeout(ctx, handshakeTimeout)
defer cancel()

Expand All @@ -280,6 +255,7 @@ func (s *Service) Handle(ctx context.Context, stream p2p.Stream, peerMultiaddrs

observedUnderlays, err := bzz.DeserializeUnderlays(syn.ObservedUnderlay)
if err != nil {
s.logger.Debug("handshake invalid inbound syn observed underlay payload", "payload_len", len(syn.ObservedUnderlay), "first_byte", firstByteString(syn.ObservedUnderlay), "payload_prefix", payloadPrefix(syn.ObservedUnderlay), "error", err)
return nil, ErrInvalidSyn
}

Expand Down Expand Up @@ -310,20 +286,19 @@ func (s *Service) Handle(ctx context.Context, stream p2p.Stream, peerMultiaddrs
return a.Equal(b)
})

advertisableUnderlays = p2p.FilterBee260CompatibleUnderlays(o.bee260compatibility, advertisableUnderlays)

bzzAddress, err := bzz.NewAddress(s.signer, advertisableUnderlays, s.overlay, s.networkID, s.nonce)
if err != nil {
return nil, err
}

welcomeMessage := s.GetWelcomeMessage()

peerMultiaddrs = p2p.FilterBee260CompatibleUnderlays(o.bee260compatibility, peerMultiaddrs)
synAckObservedUnderlay := bzz.SerializeUnderlays(peerMultiaddrs)
s.logger.Debug("handshake outbound synack observed underlay", "payload_len", len(synAckObservedUnderlay), "first_byte", firstByteString(synAckObservedUnderlay), "payload_prefix", payloadPrefix(synAckObservedUnderlay))

if err := w.WriteMsgWithContext(ctx, &pb.SynAck{
Syn: &pb.Syn{
ObservedUnderlay: bzz.SerializeUnderlays(peerMultiaddrs),
ObservedUnderlay: synAckObservedUnderlay,
},
Ack: &pb.Ack{
Address: &pb.BzzAddress{
Expand Down Expand Up @@ -398,8 +373,27 @@ func (s *Service) GetWelcomeMessage() string {
func (s *Service) parseCheckAck(ack *pb.Ack) (*bzz.Address, error) {
bzzAddress, err := bzz.ParseAddress(ack.Address.Underlay, ack.Address.Overlay, ack.Address.Signature, ack.Nonce, s.validateOverlay, s.networkID)
if err != nil {
s.logger.Debug("handshake invalid ack address payload", "underlay_len", len(ack.Address.Underlay), "underlay_first_byte", firstByteString(ack.Address.Underlay), "underlay_prefix", payloadPrefix(ack.Address.Underlay), "overlay_len", len(ack.Address.Overlay), "error", err)
return nil, ErrInvalidAck
}

return bzzAddress, nil
}

func firstByteString(data []byte) string {
if len(data) == 0 {
return "none"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe just ""?

}
return fmt.Sprintf("0x%02x", data[0])
}

func payloadPrefix(data []byte) string {
if len(data) == 0 {
return ""
}
n := 16
if len(data) < n {
n = len(data)
}
return fmt.Sprintf("%x", data[:n])
}
Loading