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