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