mirror of https://github.com/ethereum/go-ethereum
cmd/swarm: Smoke test for Swarm Feed (#17892)
parent
4868964bb9
commit
862d6f2fbf
@ -0,0 +1,323 @@ |
||||
package main |
||||
|
||||
import ( |
||||
"bytes" |
||||
"crypto/md5" |
||||
"fmt" |
||||
"io" |
||||
"io/ioutil" |
||||
"net/http" |
||||
"os" |
||||
"os/exec" |
||||
"strings" |
||||
"sync" |
||||
"time" |
||||
|
||||
"github.com/pborman/uuid" |
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil" |
||||
"github.com/ethereum/go-ethereum/crypto" |
||||
"github.com/ethereum/go-ethereum/log" |
||||
"github.com/ethereum/go-ethereum/swarm/multihash" |
||||
"github.com/ethereum/go-ethereum/swarm/storage/feed" |
||||
|
||||
colorable "github.com/mattn/go-colorable" |
||||
|
||||
cli "gopkg.in/urfave/cli.v1" |
||||
) |
||||
|
||||
const ( |
||||
feedRandomDataLength = 8 |
||||
) |
||||
|
||||
// TODO: retrieve with manifest + extract repeating code
|
||||
func cliFeedUploadAndSync(c *cli.Context) error { |
||||
|
||||
log.Root().SetHandler(log.CallerFileHandler(log.LvlFilterHandler(log.Lvl(verbosity), log.StreamHandler(colorable.NewColorableStderr(), log.TerminalFormat(true))))) |
||||
|
||||
defer func(now time.Time) { log.Info("total time", "time", time.Since(now), "size (kb)", filesize) }(time.Now()) |
||||
|
||||
generateEndpoints(scheme, cluster, from, to) |
||||
|
||||
log.Info("generating and uploading MRUs to " + endpoints[0] + " and syncing") |
||||
|
||||
// create a random private key to sign updates with and derive the address
|
||||
pkFile, err := ioutil.TempFile("", "swarm-feed-smoke-test") |
||||
if err != nil { |
||||
return err |
||||
} |
||||
defer pkFile.Close() |
||||
defer os.Remove(pkFile.Name()) |
||||
|
||||
privkeyHex := "0000000000000000000000000000000000000000000000000000000000001976" |
||||
privKey, err := crypto.HexToECDSA(privkeyHex) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
user := crypto.PubkeyToAddress(privKey.PublicKey) |
||||
userHex := hexutil.Encode(user.Bytes()) |
||||
|
||||
// save the private key to a file
|
||||
_, err = io.WriteString(pkFile, privkeyHex) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
|
||||
// keep hex strings for topic and subtopic
|
||||
var topicHex string |
||||
var subTopicHex string |
||||
|
||||
// and create combination hex topics for bzz-feed retrieval
|
||||
// xor'ed with topic (zero-value topic if no topic)
|
||||
var subTopicOnlyHex string |
||||
var mergedSubTopicHex string |
||||
|
||||
// generate random topic and subtopic and put a hex on them
|
||||
topicBytes, err := generateRandomData(feed.TopicLength) |
||||
topicHex = hexutil.Encode(topicBytes) |
||||
subTopicBytes, err := generateRandomData(8) |
||||
subTopicHex = hexutil.Encode(subTopicBytes) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
mergedSubTopic, err := feed.NewTopic(subTopicHex, topicBytes) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
mergedSubTopicHex = hexutil.Encode(mergedSubTopic[:]) |
||||
subTopicOnlyBytes, err := feed.NewTopic(subTopicHex, nil) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
subTopicOnlyHex = hexutil.Encode(subTopicOnlyBytes[:]) |
||||
|
||||
// create feed manifest, topic only
|
||||
var out bytes.Buffer |
||||
cmd := exec.Command("swarm", "--bzzapi", endpoints[0], "feed", "create", "--topic", topicHex, "--user", userHex) |
||||
cmd.Stdout = &out |
||||
log.Debug("create feed manifest topic cmd", "cmd", cmd) |
||||
err = cmd.Run() |
||||
if err != nil { |
||||
return err |
||||
} |
||||
manifestWithTopic := strings.TrimRight(out.String(), string([]byte{0x0a})) |
||||
if len(manifestWithTopic) != 64 { |
||||
return fmt.Errorf("unknown feed create manifest hash format (topic): (%d) %s", len(out.String()), manifestWithTopic) |
||||
} |
||||
log.Debug("create topic feed", "manifest", manifestWithTopic) |
||||
out.Reset() |
||||
|
||||
// create feed manifest, subtopic only
|
||||
cmd = exec.Command("swarm", "--bzzapi", endpoints[0], "feed", "create", "--name", subTopicHex, "--user", userHex) |
||||
cmd.Stdout = &out |
||||
log.Debug("create feed manifest subtopic cmd", "cmd", cmd) |
||||
err = cmd.Run() |
||||
if err != nil { |
||||
return err |
||||
} |
||||
manifestWithSubTopic := strings.TrimRight(out.String(), string([]byte{0x0a})) |
||||
if len(manifestWithSubTopic) != 64 { |
||||
return fmt.Errorf("unknown feed create manifest hash format (subtopic): (%d) %s", len(out.String()), manifestWithSubTopic) |
||||
} |
||||
log.Debug("create subtopic feed", "manifest", manifestWithTopic) |
||||
out.Reset() |
||||
|
||||
// create feed manifest, merged topic
|
||||
cmd = exec.Command("swarm", "--bzzapi", endpoints[0], "feed", "create", "--topic", topicHex, "--name", subTopicHex, "--user", userHex) |
||||
cmd.Stdout = &out |
||||
log.Debug("create feed manifest mergetopic cmd", "cmd", cmd) |
||||
err = cmd.Run() |
||||
if err != nil { |
||||
log.Error(err.Error()) |
||||
return err |
||||
} |
||||
manifestWithMergedTopic := strings.TrimRight(out.String(), string([]byte{0x0a})) |
||||
if len(manifestWithMergedTopic) != 64 { |
||||
return fmt.Errorf("unknown feed create manifest hash format (mergedtopic): (%d) %s", len(out.String()), manifestWithMergedTopic) |
||||
} |
||||
log.Debug("create mergedtopic feed", "manifest", manifestWithMergedTopic) |
||||
out.Reset() |
||||
|
||||
// create test data
|
||||
data, err := generateRandomData(feedRandomDataLength) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
h := md5.New() |
||||
h.Write(data) |
||||
dataHash := h.Sum(nil) |
||||
dataHex := hexutil.Encode(data) |
||||
|
||||
// update with topic
|
||||
cmd = exec.Command("swarm", "--bzzaccount", pkFile.Name(), "--bzzapi", endpoints[0], "feed", "update", "--topic", topicHex, dataHex) |
||||
cmd.Stdout = &out |
||||
log.Debug("update feed manifest topic cmd", "cmd", cmd) |
||||
err = cmd.Run() |
||||
if err != nil { |
||||
return err |
||||
} |
||||
log.Debug("feed update topic", "out", out) |
||||
out.Reset() |
||||
|
||||
// update with subtopic
|
||||
cmd = exec.Command("swarm", "--bzzaccount", pkFile.Name(), "--bzzapi", endpoints[0], "feed", "update", "--name", subTopicHex, dataHex) |
||||
cmd.Stdout = &out |
||||
log.Debug("update feed manifest subtopic cmd", "cmd", cmd) |
||||
err = cmd.Run() |
||||
if err != nil { |
||||
return err |
||||
} |
||||
log.Debug("feed update subtopic", "out", out) |
||||
out.Reset() |
||||
|
||||
// update with merged topic
|
||||
cmd = exec.Command("swarm", "--bzzaccount", pkFile.Name(), "--bzzapi", endpoints[0], "feed", "update", "--topic", topicHex, "--name", subTopicHex, dataHex) |
||||
cmd.Stdout = &out |
||||
log.Debug("update feed manifest merged topic cmd", "cmd", cmd) |
||||
err = cmd.Run() |
||||
if err != nil { |
||||
return err |
||||
} |
||||
log.Debug("feed update mergedtopic", "out", out) |
||||
out.Reset() |
||||
|
||||
time.Sleep(3 * time.Second) |
||||
|
||||
// retrieve the data
|
||||
wg := sync.WaitGroup{} |
||||
for _, endpoint := range endpoints { |
||||
// raw retrieve, topic only
|
||||
for _, hex := range []string{topicHex, subTopicOnlyHex, mergedSubTopicHex} { |
||||
wg.Add(1) |
||||
ruid := uuid.New()[:8] |
||||
go func(endpoint string, ruid string) { |
||||
for { |
||||
err := fetchFeed(hex, userHex, endpoint, dataHash, ruid) |
||||
if err != nil { |
||||
continue |
||||
} |
||||
|
||||
wg.Done() |
||||
return |
||||
} |
||||
}(endpoint, ruid) |
||||
|
||||
} |
||||
} |
||||
wg.Wait() |
||||
log.Info("all endpoints synced random data successfully") |
||||
|
||||
// upload test file
|
||||
log.Info("uploading to " + endpoints[0] + " and syncing") |
||||
|
||||
f, cleanup := generateRandomFile(filesize * 1000) |
||||
defer cleanup() |
||||
|
||||
hash, err := upload(f, endpoints[0]) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
hashBytes, err := hexutil.Decode("0x" + hash) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
multihashHex := hexutil.Encode(multihash.ToMultihash(hashBytes)) |
||||
|
||||
fileHash, err := digest(f) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
|
||||
log.Info("uploaded successfully", "hash", hash, "digest", fmt.Sprintf("%x", fileHash)) |
||||
|
||||
// update file with topic
|
||||
cmd = exec.Command("swarm", "--bzzaccount", pkFile.Name(), "--bzzapi", endpoints[0], "feed", "update", "--topic", topicHex, multihashHex) |
||||
cmd.Stdout = &out |
||||
err = cmd.Run() |
||||
if err != nil { |
||||
return err |
||||
} |
||||
log.Debug("feed update topic", "out", out) |
||||
out.Reset() |
||||
|
||||
// update file with subtopic
|
||||
cmd = exec.Command("swarm", "--bzzaccount", pkFile.Name(), "--bzzapi", endpoints[0], "feed", "update", "--name", subTopicHex, multihashHex) |
||||
cmd.Stdout = &out |
||||
err = cmd.Run() |
||||
if err != nil { |
||||
return err |
||||
} |
||||
log.Debug("feed update subtopic", "out", out) |
||||
out.Reset() |
||||
|
||||
// update file with merged topic
|
||||
cmd = exec.Command("swarm", "--bzzaccount", pkFile.Name(), "--bzzapi", endpoints[0], "feed", "update", "--topic", topicHex, "--name", subTopicHex, multihashHex) |
||||
cmd.Stdout = &out |
||||
err = cmd.Run() |
||||
if err != nil { |
||||
return err |
||||
} |
||||
log.Debug("feed update mergedtopic", "out", out) |
||||
out.Reset() |
||||
|
||||
time.Sleep(3 * time.Second) |
||||
|
||||
for _, endpoint := range endpoints { |
||||
|
||||
// manifest retrieve, topic only
|
||||
for _, url := range []string{manifestWithTopic, manifestWithSubTopic, manifestWithMergedTopic} { |
||||
wg.Add(1) |
||||
ruid := uuid.New()[:8] |
||||
go func(endpoint string, ruid string) { |
||||
for { |
||||
err := fetch(url, endpoint, fileHash, ruid) |
||||
if err != nil { |
||||
continue |
||||
} |
||||
|
||||
wg.Done() |
||||
return |
||||
} |
||||
}(endpoint, ruid) |
||||
} |
||||
|
||||
} |
||||
wg.Wait() |
||||
log.Info("all endpoints synced random file successfully") |
||||
|
||||
return nil |
||||
} |
||||
|
||||
func fetchFeed(topic string, user string, endpoint string, original []byte, ruid string) error { |
||||
log.Trace("sleeping", "ruid", ruid) |
||||
time.Sleep(3 * time.Second) |
||||
|
||||
log.Trace("http get request (feed)", "ruid", ruid, "api", endpoint, "topic", topic, "user", user) |
||||
res, err := http.Get(endpoint + "/bzz-feed:/?topic=" + topic + "&user=" + user) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
log.Trace("http get response (feed)", "ruid", ruid, "api", endpoint, "topic", topic, "user", user, "code", res.StatusCode, "len", res.ContentLength) |
||||
|
||||
if res.StatusCode != 200 { |
||||
return fmt.Errorf("expected status code %d, got %v (ruid %v)", 200, res.StatusCode, ruid) |
||||
} |
||||
|
||||
defer res.Body.Close() |
||||
|
||||
rdigest, err := digest(res.Body) |
||||
if err != nil { |
||||
log.Warn(err.Error(), "ruid", ruid) |
||||
return err |
||||
} |
||||
|
||||
if !bytes.Equal(rdigest, original) { |
||||
err := fmt.Errorf("downloaded imported file md5=%x is not the same as the generated one=%x", rdigest, original) |
||||
log.Warn(err.Error(), "ruid", ruid) |
||||
return err |
||||
} |
||||
|
||||
log.Trace("downloaded file matches random file", "ruid", ruid, "len", res.ContentLength) |
||||
|
||||
return nil |
||||
} |
Loading…
Reference in new issue