github.com/XinFinOrg/xdcchain@v1.1.0/cmd/swarm/swarm-smoke/feed_upload_and_sync.go (about)

     1  package main
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/md5"
     6  	"fmt"
     7  	"io"
     8  	"io/ioutil"
     9  	"os"
    10  	"os/exec"
    11  	"strings"
    12  	"sync"
    13  	"time"
    14  
    15  	"github.com/ethereum/go-ethereum/common/hexutil"
    16  	"github.com/ethereum/go-ethereum/crypto"
    17  	"github.com/ethereum/go-ethereum/log"
    18  	"github.com/ethereum/go-ethereum/metrics"
    19  	"github.com/ethereum/go-ethereum/swarm/storage/feed"
    20  	"github.com/ethereum/go-ethereum/swarm/testutil"
    21  	"github.com/pborman/uuid"
    22  	cli "gopkg.in/urfave/cli.v1"
    23  )
    24  
    25  const (
    26  	feedRandomDataLength = 8
    27  )
    28  
    29  func feedUploadAndSyncCmd(ctx *cli.Context, tuid string) error {
    30  	errc := make(chan error)
    31  
    32  	go func() {
    33  		errc <- feedUploadAndSync(ctx, tuid)
    34  	}()
    35  
    36  	select {
    37  	case err := <-errc:
    38  		if err != nil {
    39  			metrics.GetOrRegisterCounter(fmt.Sprintf("%s.fail", commandName), nil).Inc(1)
    40  		}
    41  		return err
    42  	case <-time.After(time.Duration(timeout) * time.Second):
    43  		metrics.GetOrRegisterCounter(fmt.Sprintf("%s.timeout", commandName), nil).Inc(1)
    44  
    45  		return fmt.Errorf("timeout after %v sec", timeout)
    46  	}
    47  }
    48  
    49  func feedUploadAndSync(c *cli.Context, tuid string) error {
    50  	log.Info("generating and uploading feeds to " + httpEndpoint(hosts[0]) + " and syncing")
    51  
    52  	// create a random private key to sign updates with and derive the address
    53  	pkFile, err := ioutil.TempFile("", "swarm-feed-smoke-test")
    54  	if err != nil {
    55  		return err
    56  	}
    57  	defer pkFile.Close()
    58  	defer os.Remove(pkFile.Name())
    59  
    60  	privkeyHex := "0000000000000000000000000000000000000000000000000000000000001976"
    61  	privKey, err := crypto.HexToECDSA(privkeyHex)
    62  	if err != nil {
    63  		return err
    64  	}
    65  	user := crypto.PubkeyToAddress(privKey.PublicKey)
    66  	userHex := hexutil.Encode(user.Bytes())
    67  
    68  	// save the private key to a file
    69  	_, err = io.WriteString(pkFile, privkeyHex)
    70  	if err != nil {
    71  		return err
    72  	}
    73  
    74  	// keep hex strings for topic and subtopic
    75  	var topicHex string
    76  	var subTopicHex string
    77  
    78  	// and create combination hex topics for bzz-feed retrieval
    79  	// xor'ed with topic (zero-value topic if no topic)
    80  	var subTopicOnlyHex string
    81  	var mergedSubTopicHex string
    82  
    83  	// generate random topic and subtopic and put a hex on them
    84  	topicBytes, err := generateRandomData(feed.TopicLength)
    85  	topicHex = hexutil.Encode(topicBytes)
    86  	subTopicBytes, err := generateRandomData(8)
    87  	subTopicHex = hexutil.Encode(subTopicBytes)
    88  	if err != nil {
    89  		return err
    90  	}
    91  	mergedSubTopic, err := feed.NewTopic(subTopicHex, topicBytes)
    92  	if err != nil {
    93  		return err
    94  	}
    95  	mergedSubTopicHex = hexutil.Encode(mergedSubTopic[:])
    96  	subTopicOnlyBytes, err := feed.NewTopic(subTopicHex, nil)
    97  	if err != nil {
    98  		return err
    99  	}
   100  	subTopicOnlyHex = hexutil.Encode(subTopicOnlyBytes[:])
   101  
   102  	// create feed manifest, topic only
   103  	var out bytes.Buffer
   104  	cmd := exec.Command("swarm", "--bzzapi", httpEndpoint(hosts[0]), "feed", "create", "--topic", topicHex, "--user", userHex)
   105  	cmd.Stdout = &out
   106  	log.Debug("create feed manifest topic cmd", "cmd", cmd)
   107  	err = cmd.Run()
   108  	if err != nil {
   109  		return err
   110  	}
   111  	manifestWithTopic := strings.TrimRight(out.String(), string([]byte{0x0a}))
   112  	if len(manifestWithTopic) != 64 {
   113  		return fmt.Errorf("unknown feed create manifest hash format (topic): (%d) %s", len(out.String()), manifestWithTopic)
   114  	}
   115  	log.Debug("create topic feed", "manifest", manifestWithTopic)
   116  	out.Reset()
   117  
   118  	// create feed manifest, subtopic only
   119  	cmd = exec.Command("swarm", "--bzzapi", httpEndpoint(hosts[0]), "feed", "create", "--name", subTopicHex, "--user", userHex)
   120  	cmd.Stdout = &out
   121  	log.Debug("create feed manifest subtopic cmd", "cmd", cmd)
   122  	err = cmd.Run()
   123  	if err != nil {
   124  		return err
   125  	}
   126  	manifestWithSubTopic := strings.TrimRight(out.String(), string([]byte{0x0a}))
   127  	if len(manifestWithSubTopic) != 64 {
   128  		return fmt.Errorf("unknown feed create manifest hash format (subtopic): (%d) %s", len(out.String()), manifestWithSubTopic)
   129  	}
   130  	log.Debug("create subtopic feed", "manifest", manifestWithTopic)
   131  	out.Reset()
   132  
   133  	// create feed manifest, merged topic
   134  	cmd = exec.Command("swarm", "--bzzapi", httpEndpoint(hosts[0]), "feed", "create", "--topic", topicHex, "--name", subTopicHex, "--user", userHex)
   135  	cmd.Stdout = &out
   136  	log.Debug("create feed manifest mergetopic cmd", "cmd", cmd)
   137  	err = cmd.Run()
   138  	if err != nil {
   139  		log.Error(err.Error())
   140  		return err
   141  	}
   142  	manifestWithMergedTopic := strings.TrimRight(out.String(), string([]byte{0x0a}))
   143  	if len(manifestWithMergedTopic) != 64 {
   144  		return fmt.Errorf("unknown feed create manifest hash format (mergedtopic): (%d) %s", len(out.String()), manifestWithMergedTopic)
   145  	}
   146  	log.Debug("create mergedtopic feed", "manifest", manifestWithMergedTopic)
   147  	out.Reset()
   148  
   149  	// create test data
   150  	data, err := generateRandomData(feedRandomDataLength)
   151  	if err != nil {
   152  		return err
   153  	}
   154  	h := md5.New()
   155  	h.Write(data)
   156  	dataHash := h.Sum(nil)
   157  	dataHex := hexutil.Encode(data)
   158  
   159  	// update with topic
   160  	cmd = exec.Command("swarm", "--bzzaccount", pkFile.Name(), "--bzzapi", httpEndpoint(hosts[0]), "feed", "update", "--topic", topicHex, dataHex)
   161  	cmd.Stdout = &out
   162  	log.Debug("update feed manifest topic cmd", "cmd", cmd)
   163  	err = cmd.Run()
   164  	if err != nil {
   165  		return err
   166  	}
   167  	log.Debug("feed update topic", "out", out)
   168  	out.Reset()
   169  
   170  	// update with subtopic
   171  	cmd = exec.Command("swarm", "--bzzaccount", pkFile.Name(), "--bzzapi", httpEndpoint(hosts[0]), "feed", "update", "--name", subTopicHex, dataHex)
   172  	cmd.Stdout = &out
   173  	log.Debug("update feed manifest subtopic cmd", "cmd", cmd)
   174  	err = cmd.Run()
   175  	if err != nil {
   176  		return err
   177  	}
   178  	log.Debug("feed update subtopic", "out", out)
   179  	out.Reset()
   180  
   181  	// update with merged topic
   182  	cmd = exec.Command("swarm", "--bzzaccount", pkFile.Name(), "--bzzapi", httpEndpoint(hosts[0]), "feed", "update", "--topic", topicHex, "--name", subTopicHex, dataHex)
   183  	cmd.Stdout = &out
   184  	log.Debug("update feed manifest merged topic cmd", "cmd", cmd)
   185  	err = cmd.Run()
   186  	if err != nil {
   187  		return err
   188  	}
   189  	log.Debug("feed update mergedtopic", "out", out)
   190  	out.Reset()
   191  
   192  	time.Sleep(3 * time.Second)
   193  
   194  	// retrieve the data
   195  	wg := sync.WaitGroup{}
   196  	for _, host := range hosts {
   197  		// raw retrieve, topic only
   198  		for _, hex := range []string{topicHex, subTopicOnlyHex, mergedSubTopicHex} {
   199  			wg.Add(1)
   200  			ruid := uuid.New()[:8]
   201  			go func(hex string, endpoint string, ruid string) {
   202  				for {
   203  					err := fetchFeed(hex, userHex, httpEndpoint(host), dataHash, ruid)
   204  					if err != nil {
   205  						continue
   206  					}
   207  
   208  					wg.Done()
   209  					return
   210  				}
   211  			}(hex, httpEndpoint(host), ruid)
   212  		}
   213  	}
   214  	wg.Wait()
   215  	log.Info("all endpoints synced random data successfully")
   216  
   217  	// upload test file
   218  	log.Info("feed uploading to "+httpEndpoint(hosts[0])+" and syncing", "seed", seed)
   219  
   220  	randomBytes := testutil.RandomBytes(seed, filesize*1000)
   221  
   222  	hash, err := upload(randomBytes, httpEndpoint(hosts[0]))
   223  	if err != nil {
   224  		return err
   225  	}
   226  	hashBytes, err := hexutil.Decode("0x" + hash)
   227  	if err != nil {
   228  		return err
   229  	}
   230  	multihashHex := hexutil.Encode(hashBytes)
   231  	fileHash := h.Sum(nil)
   232  
   233  	log.Info("uploaded successfully", "hash", hash, "digest", fmt.Sprintf("%x", fileHash))
   234  
   235  	// update file with topic
   236  	cmd = exec.Command("swarm", "--bzzaccount", pkFile.Name(), "--bzzapi", httpEndpoint(hosts[0]), "feed", "update", "--topic", topicHex, multihashHex)
   237  	cmd.Stdout = &out
   238  	err = cmd.Run()
   239  	if err != nil {
   240  		return err
   241  	}
   242  	log.Debug("feed update topic", "out", out)
   243  	out.Reset()
   244  
   245  	// update file with subtopic
   246  	cmd = exec.Command("swarm", "--bzzaccount", pkFile.Name(), "--bzzapi", httpEndpoint(hosts[0]), "feed", "update", "--name", subTopicHex, multihashHex)
   247  	cmd.Stdout = &out
   248  	err = cmd.Run()
   249  	if err != nil {
   250  		return err
   251  	}
   252  	log.Debug("feed update subtopic", "out", out)
   253  	out.Reset()
   254  
   255  	// update file with merged topic
   256  	cmd = exec.Command("swarm", "--bzzaccount", pkFile.Name(), "--bzzapi", httpEndpoint(hosts[0]), "feed", "update", "--topic", topicHex, "--name", subTopicHex, multihashHex)
   257  	cmd.Stdout = &out
   258  	err = cmd.Run()
   259  	if err != nil {
   260  		return err
   261  	}
   262  	log.Debug("feed update mergedtopic", "out", out)
   263  	out.Reset()
   264  
   265  	time.Sleep(3 * time.Second)
   266  
   267  	for _, host := range hosts {
   268  
   269  		// manifest retrieve, topic only
   270  		for _, url := range []string{manifestWithTopic, manifestWithSubTopic, manifestWithMergedTopic} {
   271  			wg.Add(1)
   272  			ruid := uuid.New()[:8]
   273  			go func(url string, endpoint string, ruid string) {
   274  				for {
   275  					err := fetch(url, endpoint, fileHash, ruid, "")
   276  					if err != nil {
   277  						continue
   278  					}
   279  
   280  					wg.Done()
   281  					return
   282  				}
   283  			}(url, httpEndpoint(host), ruid)
   284  		}
   285  
   286  	}
   287  	wg.Wait()
   288  	log.Info("all endpoints synced random file successfully")
   289  
   290  	return nil
   291  }