Skip to content

Commit 1833d7a

Browse files
authored
fix: support legacy format (#5498)
1 parent 680e893 commit 1833d7a

2 files changed

Lines changed: 54 additions & 5 deletions

File tree

pkg/bzz/underlay.go

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,27 @@ const maxUnderlaysPerPeer = 20
3939
const maxUnderlayBytes = 2048
4040

4141
// SerializeUnderlays serializes a slice of multiaddrs into a single byte slice.
42+
// If the slice contains exactly one address, the standard, backward-compatible
43+
// multiaddr format is used. For zero or more than one address, a custom list format
44+
// prefixed with a magic byte is utilized.
45+
// Returns an error wrapping ErrUnderlayCountExceeded or ErrUnderlayByteSizeExceeded
46+
// if the limits are violated.
4247
func SerializeUnderlays(addrs []multiaddr.Multiaddr) ([]byte, error) {
4348
if len(addrs) > maxUnderlaysPerPeer {
4449
return nil, fmt.Errorf("underlay count %d exceeds maximum of %d: %w", len(addrs), maxUnderlaysPerPeer, ErrUnderlayCountExceeded)
4550
}
4651

47-
// The format is: [prefix_byte][varint_len_1][addr_1_bytes][varint_len_2][addr_2_bytes]...
52+
// Backward compatibility if exactly one address is present.
53+
if len(addrs) == 1 {
54+
b := addrs[0].Bytes()
55+
if len(b) > maxUnderlayBytes {
56+
return nil, fmt.Errorf("underlay data size %d exceeds maximum of %d bytes: %w", len(b), maxUnderlayBytes, ErrUnderlayByteSizeExceeded)
57+
}
58+
return b, nil
59+
}
60+
61+
// For 0 or 2+ addresses, the custom list format with the prefix is used.
62+
// The format is: [prefix_byte][varint_len_1][addr_1_bytes]...
4863
var buf bytes.Buffer
4964
buf.WriteByte(underlayListPrefix)
5065

@@ -62,6 +77,8 @@ func SerializeUnderlays(addrs []multiaddr.Multiaddr) ([]byte, error) {
6277
}
6378

6479
// DeserializeUnderlays deserializes a byte slice into a slice of multiaddrs.
80+
// The data format is automatically detected as either a single legacy multiaddr
81+
// or a list of multiaddrs (identified by underlayListPrefix), and is parsed accordingly.
6582
func DeserializeUnderlays(data []byte) ([]multiaddr.Multiaddr, error) {
6683
if len(data) == 0 {
6784
return nil, errors.New("cannot deserialize empty byte slice")
@@ -71,14 +88,22 @@ func DeserializeUnderlays(data []byte) ([]multiaddr.Multiaddr, error) {
7188
return nil, fmt.Errorf("underlay data size %d exceeds maximum of %d bytes: %w", len(data), maxUnderlayBytes, ErrUnderlayByteSizeExceeded)
7289
}
7390

74-
if data[0] != underlayListPrefix {
75-
return nil, errors.New("invalid underlay payload: missing list prefix")
91+
// If the data begins with the magic prefix, it is handled as a list.
92+
if data[0] == underlayListPrefix {
93+
return deserializeList(data[1:])
7694
}
7795

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

81-
// deserializeList handles the parsing of the underlays list format.
105+
// deserializeList handles the parsing of the custom list format.
106+
// The provided data is expected to have already been stripped of the underlayListPrefix.
82107
func deserializeList(data []byte) ([]multiaddr.Multiaddr, error) {
83108
var addrs []multiaddr.Multiaddr
84109
r := bytes.NewReader(data)

pkg/bzz/underlay_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,19 @@ func TestSerializeUnderlays(t *testing.T) {
2929
}
3030
})
3131

32+
t.Run("single address list", func(t *testing.T) {
33+
addrs := []multiaddr.Multiaddr{dnsSwarmAddr}
34+
serialized := mustSerializeUnderlays(t, addrs)
35+
expected := dnsSwarmAddr.Bytes() // Should be legacy format without prefix
36+
37+
if !bytes.Equal(serialized, expected) {
38+
t.Errorf("expected single address to serialize to legacy format %x, got %x", expected, serialized)
39+
}
40+
if serialized[0] == bzz.UnderlayListPrefix {
41+
t.Error("single address serialization should not have the list prefix")
42+
}
43+
})
44+
3245
t.Run("empty list", func(t *testing.T) {
3346
addrs := []multiaddr.Multiaddr{}
3447
serialized := mustSerializeUnderlays(t, addrs)
@@ -77,6 +90,17 @@ func TestDeserializeUnderlays(t *testing.T) {
7790
}
7891
})
7992

93+
t.Run("single legacy multiaddr", func(t *testing.T) {
94+
singleBytes := wssAddr.Bytes()
95+
deserialized, err := bzz.DeserializeUnderlays(singleBytes)
96+
if err != nil {
97+
t.Fatalf("unexpected error: %v", err)
98+
}
99+
if len(deserialized) != 1 || !deserialized[0].Equal(wssAddr) {
100+
t.Errorf("expected [%v], got %v", wssAddr, deserialized)
101+
}
102+
})
103+
80104
t.Run("empty byte slice", func(t *testing.T) {
81105
_, err := bzz.DeserializeUnderlays([]byte{})
82106
if err == nil {

0 commit comments

Comments
 (0)