github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/swarm/storage/feed/handler_test.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 19:16:44</date> 10 //</624450118967365632> 11 12 13 package feed 14 15 import ( 16 "bytes" 17 "context" 18 "flag" 19 "fmt" 20 "io/ioutil" 21 "os" 22 "testing" 23 "time" 24 25 "github.com/ethereum/go-ethereum/crypto" 26 "github.com/ethereum/go-ethereum/log" 27 "github.com/ethereum/go-ethereum/swarm/chunk" 28 "github.com/ethereum/go-ethereum/swarm/storage" 29 "github.com/ethereum/go-ethereum/swarm/storage/feed/lookup" 30 ) 31 32 var ( 33 loglevel = flag.Int("loglevel", 3, "loglevel") 34 startTime = Timestamp{ 35 Time: uint64(4200), 36 } 37 cleanF func() 38 subtopicName = "føø.bar" 39 ) 40 41 func init() { 42 flag.Parse() 43 log.Root().SetHandler(log.CallerFileHandler(log.LvlFilterHandler(log.Lvl(*loglevel), log.StreamHandler(os.Stderr, log.TerminalFormat(true))))) 44 } 45 46 //模拟时间提供程序 47 type fakeTimeProvider struct { 48 currentTime uint64 49 } 50 51 func (f *fakeTimeProvider) Tick() { 52 f.currentTime++ 53 } 54 55 func (f *fakeTimeProvider) Set(time uint64) { 56 f.currentTime = time 57 } 58 59 func (f *fakeTimeProvider) FastForward(offset uint64) { 60 f.currentTime += offset 61 } 62 63 func (f *fakeTimeProvider) Now() Timestamp { 64 return Timestamp{ 65 Time: f.currentTime, 66 } 67 } 68 69 //根据期间和版本进行更新并检索它们 70 func TestFeedsHandler(t *testing.T) { 71 72 //生成假时间提供程序 73 clock := &fakeTimeProvider{ 74 currentTime: startTime.Time, //时钟从t=4200开始 75 } 76 77 //包含私钥的签名者 78 signer := newAliceSigner() 79 80 feedsHandler, datadir, teardownTest, err := setupTest(clock, signer) 81 if err != nil { 82 t.Fatal(err) 83 } 84 defer teardownTest() 85 86 //创建新源 87 ctx, cancel := context.WithCancel(context.Background()) 88 defer cancel() 89 90 topic, _ := NewTopic("Mess with Swarm feeds code and see what ghost catches you", nil) 91 fd := Feed{ 92 Topic: topic, 93 User: signer.Address(), 94 } 95 96 //更新数据: 97 updates := []string{ 98 "blinky", //t=4200 99 "pinky", //t=4242 100 "inky", //t=4284 101 "clyde", //t=4285 102 } 103 104 request := NewFirstRequest(fd.Topic) //此时间戳更新时间t=4200(开始时间) 105 chunkAddress := make(map[string]storage.Address) 106 data := []byte(updates[0]) 107 request.SetData(data) 108 if err := request.Sign(signer); err != nil { 109 t.Fatal(err) 110 } 111 chunkAddress[updates[0]], err = feedsHandler.Update(ctx, request) 112 if err != nil { 113 t.Fatal(err) 114 } 115 116 //向前移动时钟21秒 117 clock.FastForward(21) //t=4221 118 119 request, err = feedsHandler.NewRequest(ctx, &request.Feed) //此时间戳更新t=4221 120 if err != nil { 121 t.Fatal(err) 122 } 123 if request.Epoch.Base() != 0 || request.Epoch.Level != lookup.HighestLevel-1 { 124 t.Fatalf("Suggested epoch BaseTime should be 0 and Epoch level should be %d", lookup.HighestLevel-1) 125 } 126 127 request.Epoch.Level = lookup.HighestLevel //强制25级而不是24级使其失效 128 data = []byte(updates[1]) 129 request.SetData(data) 130 if err := request.Sign(signer); err != nil { 131 t.Fatal(err) 132 } 133 chunkAddress[updates[1]], err = feedsHandler.Update(ctx, request) 134 if err == nil { 135 t.Fatal("Expected update to fail since an update in this epoch already exists") 136 } 137 138 //向前移动时钟21秒 139 clock.FastForward(21) //t=4242 140 request, err = feedsHandler.NewRequest(ctx, &request.Feed) 141 if err != nil { 142 t.Fatal(err) 143 } 144 request.SetData(data) 145 if err := request.Sign(signer); err != nil { 146 t.Fatal(err) 147 } 148 chunkAddress[updates[1]], err = feedsHandler.Update(ctx, request) 149 if err != nil { 150 t.Fatal(err) 151 } 152 153 //向前移动时钟42秒 154 clock.FastForward(42) //t=4284 155 request, err = feedsHandler.NewRequest(ctx, &request.Feed) 156 if err != nil { 157 t.Fatal(err) 158 } 159 data = []byte(updates[2]) 160 request.SetData(data) 161 if err := request.Sign(signer); err != nil { 162 t.Fatal(err) 163 } 164 chunkAddress[updates[2]], err = feedsHandler.Update(ctx, request) 165 if err != nil { 166 t.Fatal(err) 167 } 168 169 //向前拨钟1秒 170 clock.FastForward(1) //t=4285 171 request, err = feedsHandler.NewRequest(ctx, &request.Feed) 172 if err != nil { 173 t.Fatal(err) 174 } 175 if request.Epoch.Base() != 0 || request.Epoch.Level != 22 { 176 t.Fatalf("Expected epoch base time to be %d, got %d. Expected epoch level to be %d, got %d", 0, request.Epoch.Base(), 22, request.Epoch.Level) 177 } 178 data = []byte(updates[3]) 179 request.SetData(data) 180 181 if err := request.Sign(signer); err != nil { 182 t.Fatal(err) 183 } 184 chunkAddress[updates[3]], err = feedsHandler.Update(ctx, request) 185 if err != nil { 186 t.Fatal(err) 187 } 188 189 time.Sleep(time.Second) 190 feedsHandler.Close() 191 192 //检查关闭后我们可以检索更新 193 clock.FastForward(2000) //t=6285 194 195 feedParams := &HandlerParams{} 196 197 feedsHandler2, err := NewTestHandler(datadir, feedParams) 198 if err != nil { 199 t.Fatal(err) 200 } 201 202 update2, err := feedsHandler2.Lookup(ctx, NewQueryLatest(&request.Feed, lookup.NoClue)) 203 if err != nil { 204 t.Fatal(err) 205 } 206 207 //最后一次更新应该是“clyde” 208 if !bytes.Equal(update2.data, []byte(updates[len(updates)-1])) { 209 t.Fatalf("feed update data was %v, expected %v", string(update2.data), updates[len(updates)-1]) 210 } 211 if update2.Level != 22 { 212 t.Fatalf("feed update epoch level was %d, expected 22", update2.Level) 213 } 214 if update2.Base() != 0 { 215 t.Fatalf("feed update epoch base time was %d, expected 0", update2.Base()) 216 } 217 log.Debug("Latest lookup", "epoch base time", update2.Base(), "epoch level", update2.Level, "data", update2.data) 218 219 //特定时间点 220 update, err := feedsHandler2.Lookup(ctx, NewQuery(&request.Feed, 4284, lookup.NoClue)) 221 if err != nil { 222 t.Fatal(err) 223 } 224 //检查数据 225 if !bytes.Equal(update.data, []byte(updates[2])) { 226 t.Fatalf("feed update data (historical) was %v, expected %v", string(update2.data), updates[2]) 227 } 228 log.Debug("Historical lookup", "epoch base time", update2.Base(), "epoch level", update2.Level, "data", update2.data) 229 230 //超过第一个会产生错误 231 update, err = feedsHandler2.Lookup(ctx, NewQuery(&request.Feed, startTime.Time-1, lookup.NoClue)) 232 if err == nil { 233 t.Fatalf("expected previous to fail, returned epoch %s data %v", update.Epoch.String(), update.data) 234 } 235 236 } 237 238 const Day = 60 * 60 * 24 239 const Year = Day * 365 240 const Month = Day * 30 241 242 func generateData(x uint64) []byte { 243 return []byte(fmt.Sprintf("%d", x)) 244 } 245 246 func TestSparseUpdates(t *testing.T) { 247 248 //生成假时间提供程序 249 timeProvider := &fakeTimeProvider{ 250 currentTime: startTime.Time, 251 } 252 253 //包含私钥的签名者 254 signer := newAliceSigner() 255 256 rh, datadir, teardownTest, err := setupTest(timeProvider, signer) 257 if err != nil { 258 t.Fatal(err) 259 } 260 defer teardownTest() 261 defer os.RemoveAll(datadir) 262 263 //创建新源 264 ctx, cancel := context.WithCancel(context.Background()) 265 defer cancel() 266 topic, _ := NewTopic("Very slow updates", nil) 267 fd := Feed{ 268 Topic: topic, 269 User: signer.Address(), 270 } 271 272 //从UNIX 0到今天,每5年发布一次更新 273 today := uint64(1533799046) 274 var epoch lookup.Epoch 275 var lastUpdateTime uint64 276 for T := uint64(0); T < today; T += 5 * Year { 277 request := NewFirstRequest(fd.Topic) 278 request.Epoch = lookup.GetNextEpoch(epoch, T) 279 request.data = generateData(T) //这会生成一些依赖于t的数据,因此我们可以稍后检查 280 request.Sign(signer) 281 if err != nil { 282 t.Fatal(err) 283 } 284 285 if _, err := rh.Update(ctx, request); err != nil { 286 t.Fatal(err) 287 } 288 epoch = request.Epoch 289 lastUpdateTime = T 290 } 291 292 query := NewQuery(&fd, today, lookup.NoClue) 293 294 _, err = rh.Lookup(ctx, query) 295 if err != nil { 296 t.Fatal(err) 297 } 298 299 _, content, err := rh.GetContent(&fd) 300 if err != nil { 301 t.Fatal(err) 302 } 303 304 if !bytes.Equal(generateData(lastUpdateTime), content) { 305 t.Fatalf("Expected to recover last written value %d, got %s", lastUpdateTime, string(content)) 306 } 307 308 //查找最接近35*年+6*月(~2005年6月)的更新: 309 //因为我们每5年更新一次,所以应该可以找到35*年的更新。 310 311 query.TimeLimit = 35*Year + 6*Month 312 313 _, err = rh.Lookup(ctx, query) 314 if err != nil { 315 t.Fatal(err) 316 } 317 318 _, content, err = rh.GetContent(&fd) 319 if err != nil { 320 t.Fatal(err) 321 } 322 323 if !bytes.Equal(generateData(35*Year), content) { 324 t.Fatalf("Expected to recover %d, got %s", 35*Year, string(content)) 325 } 326 } 327 328 func TestValidator(t *testing.T) { 329 330 //生成假时间提供程序 331 timeProvider := &fakeTimeProvider{ 332 currentTime: startTime.Time, 333 } 334 335 //包含私钥的签名者。爱丽丝会是个好女孩 336 signer := newAliceSigner() 337 338 //设置SIM时间提供程序 339 rh, _, teardownTest, err := setupTest(timeProvider, signer) 340 if err != nil { 341 t.Fatal(err) 342 } 343 defer teardownTest() 344 345 //创建新的饲料 346 topic, _ := NewTopic(subtopicName, nil) 347 fd := Feed{ 348 Topic: topic, 349 User: signer.Address(), 350 } 351 mr := NewFirstRequest(fd.Topic) 352 353 //带地址的块 354 data := []byte("foo") 355 mr.SetData(data) 356 if err := mr.Sign(signer); err != nil { 357 t.Fatalf("sign fail: %v", err) 358 } 359 360 chunk, err := mr.toChunk() 361 if err != nil { 362 t.Fatal(err) 363 } 364 if !rh.Validate(chunk) { 365 t.Fatal("Chunk validator fail on update chunk") 366 } 367 368 address := chunk.Address() 369 //弄乱地址 370 address[0] = 11 371 address[15] = 99 372 373 if rh.Validate(storage.NewChunk(address, chunk.Data())) { 374 t.Fatal("Expected Validate to fail with false chunk address") 375 } 376 } 377 378 //测试内容地址验证器是否正确检查数据 379 //通过内容地址验证器传递源更新块的测试 380 //这个测试中有一些冗余,因为它还测试内容寻址块, 381 //此验证器应将其评估为无效块 382 func TestValidatorInStore(t *testing.T) { 383 384 //生成假时间提供程序 385 TimestampProvider = &fakeTimeProvider{ 386 currentTime: startTime.Time, 387 } 388 389 //包含私钥的签名者 390 signer := newAliceSigner() 391 392 //设置本地存储 393 datadir, err := ioutil.TempDir("", "storage-testfeedsvalidator") 394 if err != nil { 395 t.Fatal(err) 396 } 397 defer os.RemoveAll(datadir) 398 399 handlerParams := storage.NewDefaultLocalStoreParams() 400 handlerParams.Init(datadir) 401 store, err := storage.NewLocalStore(handlerParams, nil) 402 if err != nil { 403 t.Fatal(err) 404 } 405 406 //设置Swarm Feeds处理程序并将其添加为本地商店的验证程序 407 fhParams := &HandlerParams{} 408 fh := NewHandler(fhParams) 409 store.Validators = append(store.Validators, fh) 410 411 //创建内容寻址块,一个好,一个坏 412 chunks := storage.GenerateRandomChunks(chunk.DefaultSize, 2) 413 goodChunk := chunks[0] 414 badChunk := storage.NewChunk(chunks[1].Address(), goodChunk.Data()) 415 416 topic, _ := NewTopic("xyzzy", nil) 417 fd := Feed{ 418 Topic: topic, 419 User: signer.Address(), 420 } 421 422 //使用正确的PublicKey创建源更新区块 423 id := ID{ 424 Epoch: lookup.Epoch{Time: 42, 425 Level: 1, 426 }, 427 Feed: fd, 428 } 429 430 updateAddr := id.Addr() 431 data := []byte("bar") 432 433 r := new(Request) 434 r.idAddr = updateAddr 435 r.Update.ID = id 436 r.data = data 437 438 r.Sign(signer) 439 440 uglyChunk, err := r.toChunk() 441 if err != nil { 442 t.Fatal(err) 443 } 444 445 //将块放入存储并检查其错误状态 446 err = store.Put(context.Background(), goodChunk) 447 if err == nil { 448 t.Fatal("expected error on good content address chunk with feed update validator only, but got nil") 449 } 450 err = store.Put(context.Background(), badChunk) 451 if err == nil { 452 t.Fatal("expected error on bad content address chunk with feed update validator only, but got nil") 453 } 454 err = store.Put(context.Background(), uglyChunk) 455 if err != nil { 456 t.Fatalf("expected no error on feed update chunk with feed update validator only, but got: %s", err) 457 } 458 } 459 460 //创建RPC和源处理程序 461 func setupTest(timeProvider timestampProvider, signer Signer) (fh *TestHandler, datadir string, teardown func(), err error) { 462 463 var fsClean func() 464 var rpcClean func() 465 cleanF = func() { 466 if fsClean != nil { 467 fsClean() 468 } 469 if rpcClean != nil { 470 rpcClean() 471 } 472 } 473 474 //临时数据 475 datadir, err = ioutil.TempDir("", "fh") 476 if err != nil { 477 return nil, "", nil, err 478 } 479 fsClean = func() { 480 os.RemoveAll(datadir) 481 } 482 483 TimestampProvider = timeProvider 484 fhParams := &HandlerParams{} 485 fh, err = NewTestHandler(datadir, fhParams) 486 return fh, datadir, cleanF, err 487 } 488 489 func newAliceSigner() *GenericSigner { 490 privKey, _ := crypto.HexToECDSA("deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef") 491 return NewGenericSigner(privKey) 492 } 493 494 func newBobSigner() *GenericSigner { 495 privKey, _ := crypto.HexToECDSA("accedeaccedeaccedeaccedeaccedeaccedeaccedeaccedeaccedeaccedecaca") 496 return NewGenericSigner(privKey) 497 } 498 499 func newCharlieSigner() *GenericSigner { 500 privKey, _ := crypto.HexToECDSA("facadefacadefacadefacadefacadefacadefacadefacadefacadefacadefaca") 501 return NewGenericSigner(privKey) 502 } 503