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