github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/swarm/storage/mru/resource_test.go (about)

     1  
     2  //此源码被清华学神尹成大魔王专业翻译分析并修改
     3  //尹成QQ77025077
     4  //尹成微信18510341407
     5  //尹成所在QQ群721929980
     6  //尹成邮箱 yinc13@mails.tsinghua.edu.cn
     7  //尹成毕业于清华大学,微软区块链领域全球最有价值专家
     8  //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620
     9  //
    10  //
    11  //
    12  //
    13  //
    14  //
    15  //
    16  //
    17  //
    18  //
    19  //
    20  //
    21  //
    22  //
    23  //
    24  
    25  package mru
    26  
    27  import (
    28  	"bytes"
    29  	"context"
    30  	"crypto/rand"
    31  	"encoding/binary"
    32  	"flag"
    33  	"io/ioutil"
    34  	"os"
    35  	"testing"
    36  	"time"
    37  
    38  	"github.com/ethereum/go-ethereum/contracts/ens"
    39  	"github.com/ethereum/go-ethereum/crypto"
    40  	"github.com/ethereum/go-ethereum/log"
    41  	"github.com/ethereum/go-ethereum/swarm/chunk"
    42  	"github.com/ethereum/go-ethereum/swarm/multihash"
    43  	"github.com/ethereum/go-ethereum/swarm/storage"
    44  )
    45  
    46  var (
    47  	loglevel   = flag.Int("loglevel", 3, "loglevel")
    48  	testHasher = storage.MakeHashFunc(resourceHashAlgorithm)()
    49  	startTime  = Timestamp{
    50  		Time: uint64(4200),
    51  	}
    52  	resourceFrequency = uint64(42)
    53  	cleanF            func()
    54  	resourceName      = "føø.bar"
    55  	hashfunc          = storage.MakeHashFunc(storage.DefaultHash)
    56  )
    57  
    58  func init() {
    59  	flag.Parse()
    60  	log.Root().SetHandler(log.CallerFileHandler(log.LvlFilterHandler(log.Lvl(*loglevel), log.StreamHandler(os.Stderr, log.TerminalFormat(true)))))
    61  }
    62  
    63  //
    64  type fakeTimeProvider struct {
    65  	currentTime uint64
    66  }
    67  
    68  func (f *fakeTimeProvider) Tick() {
    69  	f.currentTime++
    70  }
    71  
    72  func (f *fakeTimeProvider) Now() Timestamp {
    73  	return Timestamp{
    74  		Time: f.currentTime,
    75  	}
    76  }
    77  
    78  func TestUpdateChunkSerializationErrorChecking(t *testing.T) {
    79  
    80  //
    81  	var r SignedResourceUpdate
    82  	if err := r.fromChunk(storage.ZeroAddr, make([]byte, minimumUpdateDataLength-1)); err == nil {
    83  		t.Fatalf("Expected parseUpdate to fail when chunkData contains less than %d bytes", minimumUpdateDataLength)
    84  	}
    85  
    86  	r = SignedResourceUpdate{}
    87  //
    88  	fakeChunk := make([]byte, 150)
    89  	binary.LittleEndian.PutUint16(fakeChunk, 44)
    90  	if err := r.fromChunk(storage.ZeroAddr, fakeChunk); err == nil {
    91  		t.Fatal("Expected parseUpdate to fail when the header length does not match the actual data array passed in")
    92  	}
    93  
    94  	r = SignedResourceUpdate{
    95  		resourceUpdate: resourceUpdate{
    96  			updateHeader: updateHeader{
    97  				UpdateLookup: UpdateLookup{
    98  
    99  rootAddr: make([]byte, 79), //
   100  				},
   101  				metaHash:  nil,
   102  				multihash: false,
   103  			},
   104  		},
   105  	}
   106  	_, err := r.toChunk()
   107  	if err == nil {
   108  		t.Fatal("Expected newUpdateChunk to fail when rootAddr or metaHash have the wrong length")
   109  	}
   110  	r.rootAddr = make([]byte, storage.KeyLength)
   111  	r.metaHash = make([]byte, storage.KeyLength)
   112  	_, err = r.toChunk()
   113  	if err == nil {
   114  		t.Fatal("Expected newUpdateChunk to fail when there is no data")
   115  	}
   116  r.data = make([]byte, 79) //
   117  	_, err = r.toChunk()
   118  	if err == nil {
   119  		t.Fatal("expected newUpdateChunk to fail when there is no signature", err)
   120  	}
   121  
   122  	alice := newAliceSigner()
   123  	if err := r.Sign(alice); err != nil {
   124  		t.Fatalf("error signing:%s", err)
   125  
   126  	}
   127  	_, err = r.toChunk()
   128  	if err != nil {
   129  		t.Fatalf("error creating update chunk:%s", err)
   130  	}
   131  
   132  	r.multihash = true
   133  r.data[1] = 79 //
   134  	if err := r.Sign(alice); err == nil {
   135  		t.Fatal("expected Sign() to fail when an invalid multihash is in data and multihash=true", err)
   136  	}
   137  }
   138  
   139  //
   140  func TestReverse(t *testing.T) {
   141  
   142  	period := uint32(4)
   143  	version := uint32(2)
   144  
   145  //
   146  	timeProvider := &fakeTimeProvider{
   147  		currentTime: startTime.Time,
   148  	}
   149  
   150  //
   151  	signer := newAliceSigner()
   152  
   153  //
   154  	_, _, teardownTest, err := setupTest(timeProvider, signer)
   155  	if err != nil {
   156  		t.Fatal(err)
   157  	}
   158  	defer teardownTest()
   159  
   160  	metadata := ResourceMetadata{
   161  		Name:      resourceName,
   162  		StartTime: startTime,
   163  		Frequency: resourceFrequency,
   164  		Owner:     signer.Address(),
   165  	}
   166  
   167  	rootAddr, metaHash, _, err := metadata.serializeAndHash()
   168  	if err != nil {
   169  		t.Fatal(err)
   170  	}
   171  
   172  //
   173  	data := make([]byte, 8)
   174  	_, err = rand.Read(data)
   175  	if err != nil {
   176  		t.Fatal(err)
   177  	}
   178  	testHasher.Reset()
   179  	testHasher.Write(data)
   180  
   181  	update := &SignedResourceUpdate{
   182  		resourceUpdate: resourceUpdate{
   183  			updateHeader: updateHeader{
   184  				UpdateLookup: UpdateLookup{
   185  					period:   period,
   186  					version:  version,
   187  					rootAddr: rootAddr,
   188  				},
   189  				metaHash: metaHash,
   190  			},
   191  			data: data,
   192  		},
   193  	}
   194  //
   195  	key := update.UpdateAddr()
   196  
   197  	if err = update.Sign(signer); err != nil {
   198  		t.Fatal(err)
   199  	}
   200  
   201  	chunk, err := update.toChunk()
   202  	if err != nil {
   203  		t.Fatal(err)
   204  	}
   205  
   206  //
   207  	var checkUpdate SignedResourceUpdate
   208  	if err := checkUpdate.fromChunk(chunk.Addr, chunk.SData); err != nil {
   209  		t.Fatal(err)
   210  	}
   211  	checkdigest, err := checkUpdate.GetDigest()
   212  	if err != nil {
   213  		t.Fatal(err)
   214  	}
   215  	recoveredaddress, err := getOwner(checkdigest, *checkUpdate.signature)
   216  	if err != nil {
   217  		t.Fatalf("Retrieve address from signature fail: %v", err)
   218  	}
   219  	originaladdress := crypto.PubkeyToAddress(signer.PrivKey.PublicKey)
   220  
   221  //
   222  	if recoveredaddress != originaladdress {
   223  		t.Fatalf("addresses dont match: %x != %x", originaladdress, recoveredaddress)
   224  	}
   225  
   226  	if !bytes.Equal(key[:], chunk.Addr[:]) {
   227  		t.Fatalf("Expected chunk key '%x', was '%x'", key, chunk.Addr)
   228  	}
   229  	if period != checkUpdate.period {
   230  		t.Fatalf("Expected period '%d', was '%d'", period, checkUpdate.period)
   231  	}
   232  	if version != checkUpdate.version {
   233  		t.Fatalf("Expected version '%d', was '%d'", version, checkUpdate.version)
   234  	}
   235  	if !bytes.Equal(data, checkUpdate.data) {
   236  		t.Fatalf("Expectedn data '%x', was '%x'", data, checkUpdate.data)
   237  	}
   238  }
   239  
   240  //
   241  func TestResourceHandler(t *testing.T) {
   242  
   243  //
   244  	timeProvider := &fakeTimeProvider{
   245  		currentTime: startTime.Time,
   246  	}
   247  
   248  //
   249  	signer := newAliceSigner()
   250  
   251  	rh, datadir, teardownTest, err := setupTest(timeProvider, signer)
   252  	if err != nil {
   253  		t.Fatal(err)
   254  	}
   255  	defer teardownTest()
   256  
   257  //
   258  	ctx, cancel := context.WithCancel(context.Background())
   259  	defer cancel()
   260  
   261  	metadata := &ResourceMetadata{
   262  		Name:      resourceName,
   263  		Frequency: resourceFrequency,
   264  		StartTime: Timestamp{Time: timeProvider.Now().Time},
   265  		Owner:     signer.Address(),
   266  	}
   267  
   268  	request, err := NewCreateUpdateRequest(metadata)
   269  	if err != nil {
   270  		t.Fatal(err)
   271  	}
   272  	request.Sign(signer)
   273  	if err != nil {
   274  		t.Fatal(err)
   275  	}
   276  	err = rh.New(ctx, request)
   277  	if err != nil {
   278  		t.Fatal(err)
   279  	}
   280  
   281  	chunk, err := rh.chunkStore.Get(context.TODO(), storage.Address(request.rootAddr))
   282  	if err != nil {
   283  		t.Fatal(err)
   284  	} else if len(chunk.SData) < 16 {
   285  		t.Fatalf("chunk data must be minimum 16 bytes, is %d", len(chunk.SData))
   286  	}
   287  
   288  	var recoveredMetadata ResourceMetadata
   289  
   290  	recoveredMetadata.binaryGet(chunk.SData)
   291  	if err != nil {
   292  		t.Fatal(err)
   293  	}
   294  	if recoveredMetadata.StartTime.Time != timeProvider.currentTime {
   295  		t.Fatalf("stored startTime %d does not match provided startTime %d", recoveredMetadata.StartTime.Time, timeProvider.currentTime)
   296  	}
   297  	if recoveredMetadata.Frequency != resourceFrequency {
   298  		t.Fatalf("stored frequency %d does not match provided frequency %d", recoveredMetadata.Frequency, resourceFrequency)
   299  	}
   300  
   301  //
   302  	updates := []string{
   303  		"blinky",
   304  		"pinky",
   305  		"inky",
   306  		"clyde",
   307  	}
   308  
   309  //
   310  	resourcekey := make(map[string]storage.Address)
   311  	fwdClock(int(resourceFrequency/2), timeProvider)
   312  	data := []byte(updates[0])
   313  	request.SetData(data, false)
   314  	if err := request.Sign(signer); err != nil {
   315  		t.Fatal(err)
   316  	}
   317  	resourcekey[updates[0]], err = rh.Update(ctx, &request.SignedResourceUpdate)
   318  	if err != nil {
   319  		t.Fatal(err)
   320  	}
   321  
   322  //
   323  	request, err = rh.NewUpdateRequest(ctx, request.rootAddr)
   324  	if err != nil {
   325  		t.Fatal(err)
   326  	}
   327  	if request.version != 2 || request.period != 1 {
   328  		t.Fatal("Suggested period should be 1 and version should be 2")
   329  	}
   330  
   331  request.version = 1 //
   332  	data = []byte(updates[1])
   333  	request.SetData(data, false)
   334  	if err := request.Sign(signer); err != nil {
   335  		t.Fatal(err)
   336  	}
   337  	resourcekey[updates[1]], err = rh.Update(ctx, &request.SignedResourceUpdate)
   338  	if err == nil {
   339  		t.Fatal("Expected update to fail since this version already exists")
   340  	}
   341  
   342  //
   343  	fwdClock(int(resourceFrequency/2), timeProvider)
   344  	request, err = rh.NewUpdateRequest(ctx, request.rootAddr)
   345  	if err != nil {
   346  		t.Fatal(err)
   347  	}
   348  	request.SetData(data, false)
   349  	if err := request.Sign(signer); err != nil {
   350  		t.Fatal(err)
   351  	}
   352  	resourcekey[updates[1]], err = rh.Update(ctx, &request.SignedResourceUpdate)
   353  	if err != nil {
   354  		t.Fatal(err)
   355  	}
   356  
   357  	fwdClock(int(resourceFrequency), timeProvider)
   358  //
   359  	request, err = rh.NewUpdateRequest(ctx, request.rootAddr)
   360  	if err != nil {
   361  		t.Fatal(err)
   362  	}
   363  	data = []byte(updates[2])
   364  	request.SetData(data, false)
   365  	if err := request.Sign(signer); err != nil {
   366  		t.Fatal(err)
   367  	}
   368  	resourcekey[updates[2]], err = rh.Update(ctx, &request.SignedResourceUpdate)
   369  	if err != nil {
   370  		t.Fatal(err)
   371  	}
   372  
   373  //
   374  	fwdClock(1, timeProvider)
   375  	request, err = rh.NewUpdateRequest(ctx, request.rootAddr)
   376  	if err != nil {
   377  		t.Fatal(err)
   378  	}
   379  	if request.period != 3 || request.version != 2 {
   380  		t.Fatal("Suggested period should be 3 and version should be 2")
   381  	}
   382  	data = []byte(updates[3])
   383  	request.SetData(data, false)
   384  
   385  	if err := request.Sign(signer); err != nil {
   386  		t.Fatal(err)
   387  	}
   388  	resourcekey[updates[3]], err = rh.Update(ctx, &request.SignedResourceUpdate)
   389  	if err != nil {
   390  		t.Fatal(err)
   391  	}
   392  
   393  	time.Sleep(time.Second)
   394  	rh.Close()
   395  
   396  //
   397  //
   398  	fwdClock(int(resourceFrequency*2)-1, timeProvider)
   399  
   400  	rhparams := &HandlerParams{}
   401  
   402  	rh2, err := NewTestHandler(datadir, rhparams)
   403  	if err != nil {
   404  		t.Fatal(err)
   405  	}
   406  
   407  	rsrc2, err := rh2.Load(context.TODO(), request.rootAddr)
   408  	if err != nil {
   409  		t.Fatal(err)
   410  	}
   411  
   412  	_, err = rh2.Lookup(ctx, LookupLatest(request.rootAddr))
   413  	if err != nil {
   414  		t.Fatal(err)
   415  	}
   416  
   417  //
   418  	if !bytes.Equal(rsrc2.data, []byte(updates[len(updates)-1])) {
   419  		t.Fatalf("resource data was %v, expected %v", string(rsrc2.data), updates[len(updates)-1])
   420  	}
   421  	if rsrc2.version != 2 {
   422  		t.Fatalf("resource version was %d, expected 2", rsrc2.version)
   423  	}
   424  	if rsrc2.period != 3 {
   425  		t.Fatalf("resource period was %d, expected 3", rsrc2.period)
   426  	}
   427  	log.Debug("Latest lookup", "period", rsrc2.period, "version", rsrc2.version, "data", rsrc2.data)
   428  
   429  //
   430  	rsrc, err := rh2.Lookup(ctx, LookupLatestVersionInPeriod(request.rootAddr, 3))
   431  	if err != nil {
   432  		t.Fatal(err)
   433  	}
   434  //
   435  	if !bytes.Equal(rsrc.data, []byte(updates[len(updates)-1])) {
   436  		t.Fatalf("resource data (historical) was %v, expected %v", string(rsrc2.data), updates[len(updates)-1])
   437  	}
   438  	log.Debug("Historical lookup", "period", rsrc2.period, "version", rsrc2.version, "data", rsrc2.data)
   439  
   440  //
   441  	lookupParams := LookupVersion(request.rootAddr, 3, 1)
   442  	rsrc, err = rh2.Lookup(ctx, lookupParams)
   443  	if err != nil {
   444  		t.Fatal(err)
   445  	}
   446  //
   447  	if !bytes.Equal(rsrc.data, []byte(updates[2])) {
   448  		t.Fatalf("resource data (historical) was %v, expected %v", string(rsrc2.data), updates[2])
   449  	}
   450  	log.Debug("Specific version lookup", "period", rsrc2.period, "version", rsrc2.version, "data", rsrc2.data)
   451  
   452  //
   453  //
   454  	for i := 1; i >= 0; i-- {
   455  		rsrc, err := rh2.LookupPrevious(ctx, lookupParams)
   456  		if err != nil {
   457  			t.Fatal(err)
   458  		}
   459  		if !bytes.Equal(rsrc.data, []byte(updates[i])) {
   460  			t.Fatalf("resource data (previous) was %v, expected %v", rsrc.data, updates[i])
   461  
   462  		}
   463  	}
   464  
   465  //
   466  	rsrc, err = rh2.LookupPrevious(ctx, lookupParams)
   467  	if err == nil {
   468  		t.Fatalf("expected previous to fail, returned period %d version %d data %v", rsrc.period, rsrc.version, rsrc.data)
   469  	}
   470  
   471  }
   472  
   473  func TestMultihash(t *testing.T) {
   474  
   475  //
   476  	timeProvider := &fakeTimeProvider{
   477  		currentTime: startTime.Time,
   478  	}
   479  
   480  //
   481  	signer := newAliceSigner()
   482  
   483  //
   484  	rh, datadir, teardownTest, err := setupTest(timeProvider, signer)
   485  	if err != nil {
   486  		t.Fatal(err)
   487  	}
   488  	defer teardownTest()
   489  
   490  //
   491  	ctx, cancel := context.WithCancel(context.Background())
   492  	defer cancel()
   493  
   494  	metadata := &ResourceMetadata{
   495  		Name:      resourceName,
   496  		Frequency: resourceFrequency,
   497  		StartTime: Timestamp{Time: timeProvider.Now().Time},
   498  		Owner:     signer.Address(),
   499  	}
   500  
   501  	mr, err := NewCreateRequest(metadata)
   502  	if err != nil {
   503  		t.Fatal(err)
   504  	}
   505  	err = rh.New(ctx, mr)
   506  	if err != nil {
   507  		t.Fatal(err)
   508  	}
   509  
   510  //
   511  //
   512  	multihashbytes := ens.EnsNode("foo")
   513  	multihashmulti := multihash.ToMultihash(multihashbytes.Bytes())
   514  	if err != nil {
   515  		t.Fatal(err)
   516  	}
   517  	mr.SetData(multihashmulti, true)
   518  	mr.Sign(signer)
   519  	if err != nil {
   520  		t.Fatal(err)
   521  	}
   522  	multihashkey, err := rh.Update(ctx, &mr.SignedResourceUpdate)
   523  	if err != nil {
   524  		t.Fatal(err)
   525  	}
   526  
   527  	sha1bytes := make([]byte, multihash.MultihashLength)
   528  	sha1multi := multihash.ToMultihash(sha1bytes)
   529  	if err != nil {
   530  		t.Fatal(err)
   531  	}
   532  	mr, err = rh.NewUpdateRequest(ctx, mr.rootAddr)
   533  	if err != nil {
   534  		t.Fatal(err)
   535  	}
   536  	mr.SetData(sha1multi, true)
   537  	mr.Sign(signer)
   538  	if err != nil {
   539  		t.Fatal(err)
   540  	}
   541  	sha1key, err := rh.Update(ctx, &mr.SignedResourceUpdate)
   542  	if err != nil {
   543  		t.Fatal(err)
   544  	}
   545  
   546  //
   547  	mr, err = rh.NewUpdateRequest(ctx, mr.rootAddr)
   548  	if err != nil {
   549  		t.Fatal(err)
   550  	}
   551  	mr.SetData(multihashmulti[1:], true)
   552  	mr.Sign(signer)
   553  	if err != nil {
   554  		t.Fatal(err)
   555  	}
   556  	_, err = rh.Update(ctx, &mr.SignedResourceUpdate)
   557  	if err == nil {
   558  		t.Fatalf("Expected update to fail with first byte skipped")
   559  	}
   560  	mr, err = rh.NewUpdateRequest(ctx, mr.rootAddr)
   561  	if err != nil {
   562  		t.Fatal(err)
   563  	}
   564  	mr.SetData(multihashmulti[:len(multihashmulti)-2], true)
   565  	mr.Sign(signer)
   566  	if err != nil {
   567  		t.Fatal(err)
   568  	}
   569  
   570  	_, err = rh.Update(ctx, &mr.SignedResourceUpdate)
   571  	if err == nil {
   572  		t.Fatalf("Expected update to fail with last byte skipped")
   573  	}
   574  
   575  	data, err := getUpdateDirect(rh.Handler, multihashkey)
   576  	if err != nil {
   577  		t.Fatal(err)
   578  	}
   579  	multihashdecode, err := multihash.FromMultihash(data)
   580  	if err != nil {
   581  		t.Fatal(err)
   582  	}
   583  	if !bytes.Equal(multihashdecode, multihashbytes.Bytes()) {
   584  		t.Fatalf("Decoded hash '%x' does not match original hash '%x'", multihashdecode, multihashbytes.Bytes())
   585  	}
   586  	data, err = getUpdateDirect(rh.Handler, sha1key)
   587  	if err != nil {
   588  		t.Fatal(err)
   589  	}
   590  	shadecode, err := multihash.FromMultihash(data)
   591  	if err != nil {
   592  		t.Fatal(err)
   593  	}
   594  	if !bytes.Equal(shadecode, sha1bytes) {
   595  		t.Fatalf("Decoded hash '%x' does not match original hash '%x'", shadecode, sha1bytes)
   596  	}
   597  	rh.Close()
   598  
   599  	rhparams := &HandlerParams{}
   600  //
   601  	rh2, err := NewTestHandler(datadir, rhparams)
   602  	if err != nil {
   603  		t.Fatal(err)
   604  	}
   605  	mr, err = NewCreateRequest(metadata)
   606  	if err != nil {
   607  		t.Fatal(err)
   608  	}
   609  	err = rh2.New(ctx, mr)
   610  	if err != nil {
   611  		t.Fatal(err)
   612  	}
   613  
   614  	mr.SetData(multihashmulti, true)
   615  	mr.Sign(signer)
   616  
   617  	if err != nil {
   618  		t.Fatal(err)
   619  	}
   620  	multihashsignedkey, err := rh2.Update(ctx, &mr.SignedResourceUpdate)
   621  	if err != nil {
   622  		t.Fatal(err)
   623  	}
   624  
   625  	mr, err = rh2.NewUpdateRequest(ctx, mr.rootAddr)
   626  	if err != nil {
   627  		t.Fatal(err)
   628  	}
   629  	mr.SetData(sha1multi, true)
   630  	mr.Sign(signer)
   631  	if err != nil {
   632  		t.Fatal(err)
   633  	}
   634  
   635  	sha1signedkey, err := rh2.Update(ctx, &mr.SignedResourceUpdate)
   636  	if err != nil {
   637  		t.Fatal(err)
   638  	}
   639  
   640  	data, err = getUpdateDirect(rh2.Handler, multihashsignedkey)
   641  	if err != nil {
   642  		t.Fatal(err)
   643  	}
   644  	multihashdecode, err = multihash.FromMultihash(data)
   645  	if err != nil {
   646  		t.Fatal(err)
   647  	}
   648  	if !bytes.Equal(multihashdecode, multihashbytes.Bytes()) {
   649  		t.Fatalf("Decoded hash '%x' does not match original hash '%x'", multihashdecode, multihashbytes.Bytes())
   650  	}
   651  	data, err = getUpdateDirect(rh2.Handler, sha1signedkey)
   652  	if err != nil {
   653  		t.Fatal(err)
   654  	}
   655  	shadecode, err = multihash.FromMultihash(data)
   656  	if err != nil {
   657  		t.Fatal(err)
   658  	}
   659  	if !bytes.Equal(shadecode, sha1bytes) {
   660  		t.Fatalf("Decoded hash '%x' does not match original hash '%x'", shadecode, sha1bytes)
   661  	}
   662  }
   663  
   664  //
   665  func TestValidator(t *testing.T) {
   666  
   667  //
   668  	timeProvider := &fakeTimeProvider{
   669  		currentTime: startTime.Time,
   670  	}
   671  
   672  //
   673  	signer := newAliceSigner()
   674  
   675  //
   676  	falseSigner := newBobSigner()
   677  
   678  //
   679  	rh, _, teardownTest, err := setupTest(timeProvider, signer)
   680  	if err != nil {
   681  		t.Fatal(err)
   682  	}
   683  	defer teardownTest()
   684  
   685  //
   686  	ctx, cancel := context.WithCancel(context.Background())
   687  	defer cancel()
   688  	metadata := &ResourceMetadata{
   689  		Name:      resourceName,
   690  		Frequency: resourceFrequency,
   691  		StartTime: Timestamp{Time: timeProvider.Now().Time},
   692  		Owner:     signer.Address(),
   693  	}
   694  	mr, err := NewCreateRequest(metadata)
   695  	if err != nil {
   696  		t.Fatal(err)
   697  	}
   698  	mr.Sign(signer)
   699  
   700  	err = rh.New(ctx, mr)
   701  	if err != nil {
   702  		t.Fatalf("Create resource fail: %v", err)
   703  	}
   704  
   705  //
   706  	data := []byte("foo")
   707  	mr.SetData(data, false)
   708  	if err := mr.Sign(signer); err != nil {
   709  		t.Fatalf("sign fail: %v", err)
   710  	}
   711  	chunk, err := mr.SignedResourceUpdate.toChunk()
   712  	if err != nil {
   713  		t.Fatal(err)
   714  	}
   715  	if !rh.Validate(chunk.Addr, chunk.SData) {
   716  		t.Fatal("Chunk validator fail on update chunk")
   717  	}
   718  
   719  //
   720  	if err := mr.Sign(falseSigner); err == nil {
   721  		t.Fatalf("Expected Sign to fail since we are using a different OwnerAddr: %v", err)
   722  	}
   723  
   724  //
   725  mr.metadata.Owner = zeroAddr //
   726  	if err := mr.Sign(falseSigner); err != nil {
   727  		t.Fatalf("sign fail: %v", err)
   728  	}
   729  
   730  	chunk, err = mr.SignedResourceUpdate.toChunk()
   731  	if err != nil {
   732  		t.Fatal(err)
   733  	}
   734  
   735  	if rh.Validate(chunk.Addr, chunk.SData) {
   736  		t.Fatal("Chunk validator did not fail on update chunk with false address")
   737  	}
   738  
   739  	ctx, cancel = context.WithTimeout(context.Background(), time.Second)
   740  	defer cancel()
   741  
   742  	metadata = &ResourceMetadata{
   743  		Name:      resourceName,
   744  		StartTime: TimestampProvider.Now(),
   745  		Frequency: resourceFrequency,
   746  		Owner:     signer.Address(),
   747  	}
   748  	chunk, _, err = metadata.newChunk()
   749  	if err != nil {
   750  		t.Fatal(err)
   751  	}
   752  
   753  	if !rh.Validate(chunk.Addr, chunk.SData) {
   754  		t.Fatal("Chunk validator fail on metadata chunk")
   755  	}
   756  }
   757  
   758  //
   759  //
   760  //
   761  //
   762  func TestValidatorInStore(t *testing.T) {
   763  
   764  //
   765  	TimestampProvider = &fakeTimeProvider{
   766  		currentTime: startTime.Time,
   767  	}
   768  
   769  //
   770  	signer := newAliceSigner()
   771  
   772  //
   773  	datadir, err := ioutil.TempDir("", "storage-testresourcevalidator")
   774  	if err != nil {
   775  		t.Fatal(err)
   776  	}
   777  	defer os.RemoveAll(datadir)
   778  
   779  	params := storage.NewDefaultLocalStoreParams()
   780  	params.Init(datadir)
   781  	store, err := storage.NewLocalStore(params, nil)
   782  	if err != nil {
   783  		t.Fatal(err)
   784  	}
   785  
   786  //
   787  	rhParams := &HandlerParams{}
   788  	rh := NewHandler(rhParams)
   789  	store.Validators = append(store.Validators, rh)
   790  
   791  //
   792  	chunks := storage.GenerateRandomChunks(chunk.DefaultSize, 2)
   793  	goodChunk := chunks[0]
   794  	badChunk := chunks[1]
   795  	badChunk.SData = goodChunk.SData
   796  
   797  	metadata := &ResourceMetadata{
   798  		StartTime: startTime,
   799  		Name:      "xyzzy",
   800  		Frequency: resourceFrequency,
   801  		Owner:     signer.Address(),
   802  	}
   803  
   804  	rootChunk, metaHash, err := metadata.newChunk()
   805  	if err != nil {
   806  		t.Fatal(err)
   807  	}
   808  //
   809  	updateLookup := UpdateLookup{
   810  		period:   42,
   811  		version:  1,
   812  		rootAddr: rootChunk.Addr,
   813  	}
   814  
   815  	updateAddr := updateLookup.UpdateAddr()
   816  	data := []byte("bar")
   817  
   818  	r := SignedResourceUpdate{
   819  		updateAddr: updateAddr,
   820  		resourceUpdate: resourceUpdate{
   821  			updateHeader: updateHeader{
   822  				UpdateLookup: updateLookup,
   823  				metaHash:     metaHash,
   824  			},
   825  			data: data,
   826  		},
   827  	}
   828  
   829  	r.Sign(signer)
   830  
   831  	uglyChunk, err := r.toChunk()
   832  	if err != nil {
   833  		t.Fatal(err)
   834  	}
   835  
   836  //
   837  	storage.PutChunks(store, goodChunk)
   838  	if goodChunk.GetErrored() == nil {
   839  		t.Fatal("expected error on good content address chunk with resource validator only, but got nil")
   840  	}
   841  	storage.PutChunks(store, badChunk)
   842  	if badChunk.GetErrored() == nil {
   843  		t.Fatal("expected error on bad content address chunk with resource validator only, but got nil")
   844  	}
   845  	storage.PutChunks(store, uglyChunk)
   846  	if err := uglyChunk.GetErrored(); err != nil {
   847  		t.Fatalf("expected no error on resource update chunk with resource validator only, but got: %s", err)
   848  	}
   849  }
   850  
   851  //
   852  func fwdClock(count int, timeProvider *fakeTimeProvider) {
   853  	for i := 0; i < count; i++ {
   854  		timeProvider.Tick()
   855  	}
   856  }
   857  
   858  //
   859  func setupTest(timeProvider timestampProvider, signer Signer) (rh *TestHandler, datadir string, teardown func(), err error) {
   860  
   861  	var fsClean func()
   862  	var rpcClean func()
   863  	cleanF = func() {
   864  		if fsClean != nil {
   865  			fsClean()
   866  		}
   867  		if rpcClean != nil {
   868  			rpcClean()
   869  		}
   870  	}
   871  
   872  //
   873  	datadir, err = ioutil.TempDir("", "rh")
   874  	if err != nil {
   875  		return nil, "", nil, err
   876  	}
   877  	fsClean = func() {
   878  		os.RemoveAll(datadir)
   879  	}
   880  
   881  	TimestampProvider = timeProvider
   882  	rhparams := &HandlerParams{}
   883  	rh, err = NewTestHandler(datadir, rhparams)
   884  	return rh, datadir, cleanF, err
   885  }
   886  
   887  func newAliceSigner() *GenericSigner {
   888  	privKey, _ := crypto.HexToECDSA("deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef")
   889  	return NewGenericSigner(privKey)
   890  }
   891  
   892  func newBobSigner() *GenericSigner {
   893  	privKey, _ := crypto.HexToECDSA("accedeaccedeaccedeaccedeaccedeaccedeaccedeaccedeaccedeaccedecaca")
   894  	return NewGenericSigner(privKey)
   895  }
   896  
   897  func newCharlieSigner() *GenericSigner {
   898  	privKey, _ := crypto.HexToECDSA("facadefacadefacadefacadefacadefacadefacadefacadefacadefacadefaca")
   899  	return NewGenericSigner(privKey)
   900  }
   901  
   902  func getUpdateDirect(rh *Handler, addr storage.Address) ([]byte, error) {
   903  	chunk, err := rh.chunkStore.Get(context.TODO(), addr)
   904  	if err != nil {
   905  		return nil, err
   906  	}
   907  	var r SignedResourceUpdate
   908  	if err := r.fromChunk(addr, chunk.SData); err != nil {
   909  		return nil, err
   910  	}
   911  	return r.data, nil
   912  }