Skip to content

Commit 2714e8f

Browse files
jpeletiernonsense
authored andcommitted
Remove multihash from Swarm bzz:// for Feeds (#18175)
1 parent 0699287 commit 2714e8f

File tree

7 files changed

+167
-226
lines changed

7 files changed

+167
-226
lines changed

cmd/swarm/swarm-smoke/feed_upload_and_sync.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import (
1616
"github.com/ethereum/go-ethereum/common/hexutil"
1717
"github.com/ethereum/go-ethereum/crypto"
1818
"github.com/ethereum/go-ethereum/log"
19-
"github.com/ethereum/go-ethereum/swarm/multihash"
2019
"github.com/ethereum/go-ethereum/swarm/storage/feed"
2120
colorable "github.com/mattn/go-colorable"
2221
"github.com/pborman/uuid"
@@ -36,7 +35,7 @@ func cliFeedUploadAndSync(c *cli.Context) error {
3635

3736
generateEndpoints(scheme, cluster, from, to)
3837

39-
log.Info("generating and uploading MRUs to " + endpoints[0] + " and syncing")
38+
log.Info("generating and uploading feeds to " + endpoints[0] + " and syncing")
4039

4140
// create a random private key to sign updates with and derive the address
4241
pkFile, err := ioutil.TempFile("", "swarm-feed-smoke-test")
@@ -218,8 +217,7 @@ func cliFeedUploadAndSync(c *cli.Context) error {
218217
if err != nil {
219218
return err
220219
}
221-
multihashHex := hexutil.Encode(multihash.ToMultihash(hashBytes))
222-
220+
multihashHex := hexutil.Encode(hashBytes)
223221
fileHash, err := digest(f)
224222
if err != nil {
225223
return err

swarm/OWNERS

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ swarm
77
├── fuse ────────────────── @jmozah, @holisticode
88
├── grafana_dashboards ──── @nonsense
99
├── metrics ─────────────── @nonsense, @holisticode
10-
├── multihash ───────────── @nolash
1110
├── network ─────────────── ethersphere
1211
│ ├── bitvector ───────── @zelig, @janos, @gbalint
1312
│ ├── priorityqueue ───── @zelig, @janos, @gbalint

swarm/api/api.go

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ import (
4242
"github.com/ethereum/go-ethereum/core/types"
4343
"github.com/ethereum/go-ethereum/metrics"
4444
"github.com/ethereum/go-ethereum/swarm/log"
45-
"github.com/ethereum/go-ethereum/swarm/multihash"
4645
"github.com/ethereum/go-ethereum/swarm/spancontext"
4746
"github.com/ethereum/go-ethereum/swarm/storage"
4847
"github.com/ethereum/go-ethereum/swarm/storage/feed"
@@ -417,31 +416,31 @@ func (a *API) Get(ctx context.Context, decrypt DecryptFunc, manifestAddr storage
417416
return reader, mimeType, status, nil, err
418417
}
419418
// get the data of the update
420-
_, rsrcData, err := a.feed.GetContent(entry.Feed)
419+
_, contentAddr, err := a.feed.GetContent(entry.Feed)
421420
if err != nil {
422421
apiGetNotFound.Inc(1)
423422
status = http.StatusNotFound
424423
log.Warn(fmt.Sprintf("get feed update content error: %v", err))
425424
return reader, mimeType, status, nil, err
426425
}
427426

428-
// extract multihash
429-
decodedMultihash, err := multihash.FromMultihash(rsrcData)
430-
if err != nil {
427+
// extract content hash
428+
if len(contentAddr) != storage.AddressLength {
431429
apiGetInvalid.Inc(1)
432430
status = http.StatusUnprocessableEntity
433-
log.Warn("invalid multihash in feed update", "err", err)
434-
return reader, mimeType, status, nil, err
431+
errorMessage := fmt.Sprintf("invalid swarm hash in feed update. Expected %d bytes. Got %d", storage.AddressLength, len(contentAddr))
432+
log.Warn(errorMessage)
433+
return reader, mimeType, status, nil, errors.New(errorMessage)
435434
}
436-
manifestAddr = storage.Address(decodedMultihash)
437-
log.Trace("feed update contains multihash", "key", manifestAddr)
435+
manifestAddr = storage.Address(contentAddr)
436+
log.Trace("feed update contains swarm hash", "key", manifestAddr)
438437

439-
// get the manifest the multihash digest points to
438+
// get the manifest the swarm hash points to
440439
trie, err := loadManifest(ctx, a.fileStore, manifestAddr, nil, NOOPDecrypt)
441440
if err != nil {
442441
apiGetNotFound.Inc(1)
443442
status = http.StatusNotFound
444-
log.Warn(fmt.Sprintf("loadManifestTrie (feed update multihash) error: %v", err))
443+
log.Warn(fmt.Sprintf("loadManifestTrie (feed update) error: %v", err))
445444
return reader, mimeType, status, nil, err
446445
}
447446

@@ -451,8 +450,8 @@ func (a *API) Get(ctx context.Context, decrypt DecryptFunc, manifestAddr storage
451450
if entry == nil {
452451
status = http.StatusNotFound
453452
apiGetNotFound.Inc(1)
454-
err = fmt.Errorf("manifest (feed update multihash) entry for '%s' not found", path)
455-
log.Trace("manifest (feed update multihash) entry not found", "key", manifestAddr, "path", path)
453+
err = fmt.Errorf("manifest (feed update) entry for '%s' not found", path)
454+
log.Trace("manifest (feed update) entry not found", "key", manifestAddr, "path", path)
456455
return reader, mimeType, status, nil, err
457456
}
458457
}

swarm/api/client/client_test.go

Lines changed: 85 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ import (
2525
"sort"
2626
"testing"
2727

28+
"github.com/ethereum/go-ethereum/swarm/storage"
2829
"github.com/ethereum/go-ethereum/swarm/storage/feed/lookup"
2930

3031
"github.com/ethereum/go-ethereum/common"
3132
"github.com/ethereum/go-ethereum/crypto"
3233
"github.com/ethereum/go-ethereum/swarm/api"
3334
swarmhttp "github.com/ethereum/go-ethereum/swarm/api/http"
34-
"github.com/ethereum/go-ethereum/swarm/multihash"
3535
"github.com/ethereum/go-ethereum/swarm/storage/feed"
3636
)
3737

@@ -368,58 +368,99 @@ func newTestSigner() (*feed.GenericSigner, error) {
368368
return feed.NewGenericSigner(privKey), nil
369369
}
370370

371-
// test the transparent resolving of multihash feed updates with bzz:// scheme
371+
// Test the transparent resolving of feed updates with bzz:// scheme
372372
//
373-
// first upload data, and store the multihash to the resulting manifest in a feed update
374-
// retrieving the update with the multihash should return the manifest pointing directly to the data
373+
// First upload data to bzz:, and store the Swarm hash to the resulting manifest in a feed update.
374+
// This effectively uses a feed to store a pointer to content rather than the content itself
375+
// Retrieving the update with the Swarm hash should return the manifest pointing directly to the data
375376
// and raw retrieve of that hash should return the data
376-
func TestClientCreateFeedMultihash(t *testing.T) {
377+
func TestClientBzzWithFeed(t *testing.T) {
377378

378379
signer, _ := newTestSigner()
379380

381+
// Initialize a Swarm test server
380382
srv := swarmhttp.NewTestSwarmServer(t, serverFunc, nil)
381-
client := NewClient(srv.URL)
383+
swarmClient := NewClient(srv.URL)
382384
defer srv.Close()
383385

384-
// add the data our multihash aliased manifest will point to
385-
databytes := []byte("bar")
386-
387-
swarmHash, err := client.UploadRaw(bytes.NewReader(databytes), int64(len(databytes)), false)
386+
// put together some data for our test:
387+
dataBytes := []byte(`
388+
//
389+
// Create some data our manifest will point to. Data that could be very big and wouldn't fit in a feed update.
390+
// So what we are going to do is upload it to Swarm bzz:// and obtain a **manifest hash** pointing to it:
391+
//
392+
// MANIFEST HASH --> DATA
393+
//
394+
// Then, we store that **manifest hash** into a Swarm Feed update. Once we have done this,
395+
// we can use the **feed manifest hash** in bzz:// instead, this way: bzz://feed-manifest-hash.
396+
//
397+
// FEED MANIFEST HASH --> MANIFEST HASH --> DATA
398+
//
399+
// Given that we can update the feed at any time with a new **manifest hash** but the **feed manifest hash**
400+
// stays constant, we have effectively created a fixed address to changing content. (Applause)
401+
//
402+
// FEED MANIFEST HASH (the same) --> MANIFEST HASH(2) --> DATA(2)
403+
//
404+
`)
405+
406+
// Create a virtual File out of memory containing the above data
407+
f := &File{
408+
ReadCloser: ioutil.NopCloser(bytes.NewReader(dataBytes)),
409+
ManifestEntry: api.ManifestEntry{
410+
ContentType: "text/plain",
411+
Mode: 0660,
412+
Size: int64(len(dataBytes)),
413+
},
414+
}
415+
416+
// upload data to bzz:// and retrieve the content-addressed manifest hash, hex-encoded.
417+
manifestAddressHex, err := swarmClient.Upload(f, "", false)
388418
if err != nil {
389-
t.Fatalf("Error uploading raw test data: %s", err)
419+
t.Fatalf("Error creating manifest: %s", err)
390420
}
391421

392-
s := common.FromHex(swarmHash)
393-
mh := multihash.ToMultihash(s)
422+
// convert the hex-encoded manifest hash to a 32-byte slice
423+
manifestAddress := common.FromHex(manifestAddressHex)
424+
425+
if len(manifestAddress) != storage.AddressLength {
426+
t.Fatalf("Something went wrong. Got a hash of an unexpected length. Expected %d bytes. Got %d", storage.AddressLength, len(manifestAddress))
427+
}
394428

395-
// our feed topic
396-
topic, _ := feed.NewTopic("foo.eth", nil)
429+
// Now create a **feed manifest**. For that, we need a topic:
430+
topic, _ := feed.NewTopic("interesting topic indeed", nil)
397431

398-
createRequest := feed.NewFirstRequest(topic)
432+
// Build a feed request to update data
433+
request := feed.NewFirstRequest(topic)
399434

400-
createRequest.SetData(mh)
401-
if err := createRequest.Sign(signer); err != nil {
435+
// Put the 32-byte address of the manifest into the feed update
436+
request.SetData(manifestAddress)
437+
438+
// Sign the update
439+
if err := request.Sign(signer); err != nil {
402440
t.Fatalf("Error signing update: %s", err)
403441
}
404442

405-
feedManifestHash, err := client.CreateFeedWithManifest(createRequest)
406-
443+
// Publish the update and at the same time request a **feed manifest** to be created
444+
feedManifestAddressHex, err := swarmClient.CreateFeedWithManifest(request)
407445
if err != nil {
408446
t.Fatalf("Error creating feed manifest: %s", err)
409447
}
410448

411-
correctManifestAddrHex := "bb056a5264c295c2b0f613c8409b9c87ce9d71576ace02458160df4cc894210b"
412-
if feedManifestHash != correctManifestAddrHex {
413-
t.Fatalf("Response feed manifest mismatch, expected '%s', got '%s'", correctManifestAddrHex, feedManifestHash)
449+
// Check we have received the exact **feed manifest** to be expected
450+
// given the topic and user signing the updates:
451+
correctFeedManifestAddrHex := "747c402e5b9dc715a25a4393147512167bab018a007fad7cdcd9adc7fce1ced2"
452+
if feedManifestAddressHex != correctFeedManifestAddrHex {
453+
t.Fatalf("Response feed manifest mismatch, expected '%s', got '%s'", correctFeedManifestAddrHex, feedManifestAddressHex)
414454
}
415455

416456
// Check we get a not found error when trying to get feed updates with a made-up manifest
417-
_, err = client.QueryFeed(nil, "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb")
457+
_, err = swarmClient.QueryFeed(nil, "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb")
418458
if err != ErrNoFeedUpdatesFound {
419459
t.Fatalf("Expected to receive ErrNoFeedUpdatesFound error. Got: %s", err)
420460
}
421461

422-
reader, err := client.QueryFeed(nil, correctManifestAddrHex)
462+
// If we query the feed directly we should get **manifest hash** back:
463+
reader, err := swarmClient.QueryFeed(nil, correctFeedManifestAddrHex)
423464
if err != nil {
424465
t.Fatalf("Error retrieving feed updates: %s", err)
425466
}
@@ -428,10 +469,27 @@ func TestClientCreateFeedMultihash(t *testing.T) {
428469
if err != nil {
429470
t.Fatal(err)
430471
}
431-
if !bytes.Equal(mh, gotData) {
432-
t.Fatalf("Expected: %v, got %v", mh, gotData)
472+
473+
//Check that indeed the **manifest hash** is retrieved
474+
if !bytes.Equal(manifestAddress, gotData) {
475+
t.Fatalf("Expected: %v, got %v", manifestAddress, gotData)
476+
}
477+
478+
// Now the final test we were looking for: Use bzz://<feed-manifest> and that should resolve all manifests
479+
// and return the original data directly:
480+
f, err = swarmClient.Download(feedManifestAddressHex, "")
481+
if err != nil {
482+
t.Fatal(err)
483+
}
484+
gotData, err = ioutil.ReadAll(f)
485+
if err != nil {
486+
t.Fatal(err)
433487
}
434488

489+
// Check that we get back the original data:
490+
if !bytes.Equal(dataBytes, gotData) {
491+
t.Fatalf("Expected: %v, got %v", manifestAddress, gotData)
492+
}
435493
}
436494

437495
// TestClientCreateUpdateFeed will check that feeds can be created and updated via the HTTP client.

0 commit comments

Comments
 (0)