Skip to content

Commit 2cc5d53

Browse files
authored
feat: feed legacy payload header (#5029)
Co-authored-by: nugaon <[email protected]>
1 parent 87306d6 commit 2cc5d53

File tree

9 files changed

+65
-31
lines changed

9 files changed

+65
-31
lines changed

openapi/Swarm.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,6 +1036,12 @@ paths:
10361036
$ref: "SwarmCommon.yaml#/components/schemas/FeedType"
10371037
required: false
10381038
description: "Feed indexing scheme (default: sequence)"
1039+
- in: header
1040+
name: legacy-feed-resolution
1041+
schema:
1042+
type: boolean
1043+
required: false
1044+
description: "Resolves feed payloads in legacy structure (timestamp, content address)."
10391045
- $ref: "SwarmCommon.yaml#/components/parameters/SwarmOnlyRootChunkParameter"
10401046
- $ref: "SwarmCommon.yaml#/components/parameters/SwarmCache"
10411047
- $ref: "SwarmCommon.yaml#/components/parameters/SwarmRedundancyStrategyParameter"

pkg/api/api.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ const (
7878
SwarmSocSignatureHeader = "Swarm-Soc-Signature"
7979
SwarmFeedIndexHeader = "Swarm-Feed-Index"
8080
SwarmFeedIndexNextHeader = "Swarm-Feed-Index-Next"
81+
SwarmLegacyFeedResolve = "Swarm-Feed-Legacy-Resolve"
8182
SwarmOnlyRootChunk = "Swarm-Only-Root-Chunk"
8283
SwarmCollectionHeader = "Swarm-Collection"
8384
SwarmPostageBatchIdHeader = "Swarm-Postage-Batch-Id"

pkg/api/bzz.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,7 @@ FETCH:
431431
jsonhttp.NotFound(w, "no update found")
432432
return
433433
}
434-
wc, err := feeds.GetWrappedChunk(ctx, s.storer.Download(cache), ch)
434+
wc, err := feeds.GetWrappedChunk(ctx, s.storer.Download(cache), ch, false)
435435
if err != nil {
436436
logger.Debug("bzz download: mapStructure feed update failed", "error", err)
437437
logger.Error(nil, "bzz download: mapStructure feed update failed")

pkg/api/bzz_test.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"github.com/ethersphere/bee/v2/pkg/manifest"
2727
mockbatchstore "github.com/ethersphere/bee/v2/pkg/postage/batchstore/mock"
2828
mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock"
29+
testingsoc "github.com/ethersphere/bee/v2/pkg/soc/testing"
2930
"github.com/ethersphere/bee/v2/pkg/storage/inmemchunkstore"
3031
mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock"
3132
"github.com/ethersphere/bee/v2/pkg/swarm"
@@ -794,16 +795,22 @@ func TestFeedIndirection(t *testing.T) {
794795
t.Fatalf("expected file reference, did not got any")
795796
}
796797

797-
// now use the "content" to mock the feed lookup
798+
// get root chunk of data
799+
// and wrap it in a feed
800+
rootCh, err := storer.ChunkStore().Get(context.Background(), resp.Reference)
801+
if err != nil {
802+
t.Fatal(err)
803+
}
804+
socRootCh := testingsoc.GenerateMockSOC(t, rootCh.Data()[swarm.SpanSize:]).Chunk()
805+
806+
// now use the "content" root chunk to mock the feed lookup
798807
// also, use the mocked mantaray chunks that unmarshal
799808
// into a real manifest with the mocked feed values when
800809
// called from the bzz endpoint. then call the bzz endpoint with
801810
// the pregenerated feed root manifest hash
802811

803-
feedUpdate := toChunk(t, 121212, resp.Reference.Bytes())
804-
805812
var (
806-
look = newMockLookup(-1, 0, feedUpdate, nil, &id{}, nil)
813+
look = newMockLookup(-1, 0, socRootCh, nil, &id{}, nil)
807814
factory = newMockFactory(look)
808815
bzzDownloadResource = func(addr, path string) string { return "/bzz/" + addr + "/" + path }
809816
ctx = context.Background()
@@ -813,7 +820,6 @@ func TestFeedIndirection(t *testing.T) {
813820
Logger: logger,
814821
Feeds: factory,
815822
})
816-
err := storer.Cache().Put(ctx, feedUpdate)
817823
if err != nil {
818824
t.Fatal(err)
819825
}

pkg/api/feed.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ func (s *Service) feedGetHandler(w http.ResponseWriter, r *http.Request) {
6565
}
6666

6767
headers := struct {
68-
OnlyRootChunk bool `map:"Swarm-Only-Root-Chunk"`
68+
OnlyRootChunk bool `map:"Swarm-Only-Root-Chunk"`
69+
LegacyFeedResolve bool `map:"Swarm-Feed-Legacy-Resolve"`
6970
}{}
7071
if response := s.mapStructure(r.Header, &headers); response != nil {
7172
response("invalid header params", logger, w)
@@ -102,7 +103,7 @@ func (s *Service) feedGetHandler(w http.ResponseWriter, r *http.Request) {
102103
return
103104
}
104105

105-
wc, err := feeds.GetWrappedChunk(r.Context(), s.storer.Download(false), ch)
106+
wc, err := feeds.GetWrappedChunk(r.Context(), s.storer.Download(false), ch, headers.LegacyFeedResolve)
106107
if err != nil {
107108
logger.Error(nil, "wrapped chunk cannot be retrieved")
108109
jsonhttp.NotFound(w, "wrapped chunk cannot be retrieved")

pkg/api/feed_test.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ func TestFeed_Get(t *testing.T) {
7777

7878
jsonhttptest.Request(t, client, http.MethodGet, feedResource(ownerString, "aabbcc", "12"), http.StatusOK,
7979
jsonhttptest.WithExpectedResponse(mockWrappedCh.Data()[swarm.SpanSize:]),
80+
jsonhttptest.WithRequestHeader(api.SwarmLegacyFeedResolve, "true"),
8081
jsonhttptest.WithExpectedResponseHeader(api.SwarmFeedIndexHeader, hex.EncodeToString(idBytes)),
8182
jsonhttptest.WithExpectedResponseHeader(api.AccessControlExposeHeaders, api.SwarmFeedIndexHeader),
8283
jsonhttptest.WithExpectedResponseHeader(api.AccessControlExposeHeaders, api.SwarmFeedIndexNextHeader),
@@ -86,7 +87,7 @@ func TestFeed_Get(t *testing.T) {
8687
)
8788
})
8889

89-
t.Run("latest", func(t *testing.T) {
90+
t.Run("latest with legacy payload", func(t *testing.T) {
9091
t.Parallel()
9192

9293
var (
@@ -103,6 +104,7 @@ func TestFeed_Get(t *testing.T) {
103104
)
104105

105106
jsonhttptest.Request(t, client, http.MethodGet, feedResource(ownerString, "aabbcc", ""), http.StatusOK,
107+
jsonhttptest.WithRequestHeader(api.SwarmLegacyFeedResolve, "true"),
106108
jsonhttptest.WithExpectedResponse(mockWrappedCh.Data()[swarm.SpanSize:]),
107109
jsonhttptest.WithExpectedContentLength(len(mockWrappedCh.Data()[swarm.SpanSize:])),
108110
jsonhttptest.WithExpectedResponseHeader(api.SwarmFeedIndexHeader, hex.EncodeToString(idBytes)),
@@ -161,7 +163,9 @@ func TestFeed_Get(t *testing.T) {
161163
})
162164
)
163165

164-
jsonhttptest.Request(t, client, http.MethodGet, feedResource(ownerString, "aabbcc", ""), http.StatusNotFound)
166+
jsonhttptest.Request(t, client, http.MethodGet, feedResource(ownerString, "aabbcc", ""), http.StatusNotFound,
167+
jsonhttptest.WithRequestHeader(api.SwarmLegacyFeedResolve, "true"),
168+
)
165169
})
166170

167171
t.Run("bigger payload than one chunk", func(t *testing.T) {

pkg/feeds/getter.go

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ func (f *Getter) Get(ctx context.Context, i Index) (swarm.Chunk, error) {
5050
return f.getter.Get(ctx, addr)
5151
}
5252

53-
func GetWrappedChunk(ctx context.Context, getter storage.Getter, ch swarm.Chunk) (swarm.Chunk, error) {
53+
func GetWrappedChunk(ctx context.Context, getter storage.Getter, ch swarm.Chunk, legacyResolve bool) (swarm.Chunk, error) {
5454
wc, err := FromChunk(ch)
5555
if err != nil {
5656
return nil, err
@@ -59,16 +59,15 @@ func GetWrappedChunk(ctx context.Context, getter storage.Getter, ch swarm.Chunk)
5959
// possible values right now:
6060
// unencrypted ref: span+timestamp+ref => 8+8+32=48
6161
// encrypted ref: span+timestamp+ref+decryptKey => 8+8+64=80
62-
ref, err := legacyPayload(wc)
63-
if err != nil {
64-
if errors.Is(err, errNotLegacyPayload) {
65-
return wc, nil
62+
if legacyResolve {
63+
ref, err := legacyPayload(wc)
64+
if err != nil {
65+
return nil, err
66+
}
67+
wc, err = getter.Get(ctx, ref)
68+
if err != nil {
69+
return nil, err
6670
}
67-
return nil, err
68-
}
69-
wc, err = getter.Get(ctx, ref)
70-
if err != nil {
71-
return nil, err
7271
}
7372

7473
return wc, nil

pkg/feeds/getter_test.go

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,24 @@ import (
1717
func TestGetWrappedChunk(t *testing.T) {
1818
storer := mockstorer.New()
1919

20+
data := []byte("data")
2021
// new format (wraps chunk)
21-
ch := soctesting.GenerateMockSOC(t, []byte("data")).Chunk()
22-
wch, err := GetWrappedChunk(context.Background(), storer.ChunkStore(), ch)
22+
ch := soctesting.GenerateMockSOC(t, data).Chunk()
23+
wch, err := GetWrappedChunk(context.Background(), storer.ChunkStore(), ch, false)
2324
if err != nil {
2425
t.Fatal(err)
2526
}
2627

27-
if !bytes.Equal(wch.Data()[8:], []byte("data")) {
28+
if !bytes.Equal(wch.Data()[8:], data) {
2829
t.Fatal("data mismatch")
2930
}
3031

3132
// old format
33+
err = storer.Put(context.Background(), wch)
34+
if err != nil {
35+
t.Fatal(err)
36+
}
37+
3238
tt := []struct {
3339
name string
3440
addr []byte
@@ -49,19 +55,30 @@ func TestGetWrappedChunk(t *testing.T) {
4955
binary.BigEndian.PutUint64(timestamp, 1)
5056
ch = soctesting.GenerateMockSOC(t, append(timestamp, tc.addr...)).Chunk()
5157

52-
err = storer.Put(context.Background(), wch)
58+
wch, err = GetWrappedChunk(context.Background(), storer.ChunkStore(), ch, true)
5359
if err != nil {
5460
t.Fatal(err)
5561
}
5662

57-
wch, err = GetWrappedChunk(context.Background(), storer.ChunkStore(), ch)
58-
if err != nil {
59-
t.Fatal(err)
60-
}
61-
62-
if !bytes.Equal(wch.Data()[8:], []byte("data")) {
63+
if !bytes.Equal(wch.Data()[8:], data) {
6364
t.Fatal("data mismatch")
6465
}
6566
})
6667
}
68+
69+
t.Run("returns feed legacy payload", func(t *testing.T) {
70+
timestamp := make([]byte, 8)
71+
binary.BigEndian.PutUint64(timestamp, 1)
72+
feedChData := append(timestamp, wch.Address().Bytes()...)
73+
ch = soctesting.GenerateMockSOC(t, feedChData).Chunk()
74+
75+
wch, err = GetWrappedChunk(context.Background(), storer.ChunkStore(), ch, false)
76+
if err != nil {
77+
t.Fatal(err)
78+
}
79+
80+
if !bytes.Equal(wch.Data()[8:], feedChData) {
81+
t.Fatal("data should be similar as old legacy feed payload format.")
82+
}
83+
})
6784
}

pkg/node/bootstrap.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ func getLatestSnapshot(
335335
return nil, err
336336
}
337337

338-
return feeds.GetWrappedChunk(ctx, st, u)
338+
return feeds.GetWrappedChunk(ctx, st, u, false)
339339
}
340340

341341
func batchStoreExists(s storage.StateStorer) (bool, error) {

0 commit comments

Comments
 (0)