From 0d5b951614b393f79202a13ad71c4f5a64899af6 Mon Sep 17 00:00:00 2001 From: lash Date: Wed, 28 Mar 2018 12:24:52 +0200 Subject: [PATCH] swarm/storage, swarm/api, swarm/testutil: Explicit lookup limit params --- swarm/api/api.go | 8 ++--- swarm/api/http/server.go | 6 ++-- swarm/storage/resource.go | 59 +++++++++++++++++++++------------- swarm/storage/resource_test.go | 19 +++++++---- swarm/testutil/http.go | 2 +- 5 files changed, 57 insertions(+), 37 deletions(-) diff --git a/swarm/api/api.go b/swarm/api/api.go index 3cbb884c62..f8c6ca6a58 100644 --- a/swarm/api/api.go +++ b/swarm/api/api.go @@ -579,17 +579,17 @@ func (self *Api) BuildDirectoryTree(mhash string, nameresolver bool) (key storag } // Look up mutable resource updates at specific periods and versions -func (self *Api) ResourceLookup(ctx context.Context, name string, period uint32, version uint32, maxPeriod int) (storage.Key, []byte, error) { +func (self *Api) ResourceLookup(ctx context.Context, name string, period uint32, version uint32, maxLookup *storage.ResourceLookupParams) (storage.Key, []byte, error) { var err error if version != 0 { if period == 0 { return nil, nil, storage.NewResourceError(storage.ErrInvalidValue, "Period can't be 0") } - _, err = self.resource.LookupVersionByName(ctx, name, period, version, true, maxPeriod) + _, err = self.resource.LookupVersionByName(ctx, name, period, version, true, maxLookup) } else if period != 0 { - _, err = self.resource.LookupHistoricalByName(ctx, name, period, true, maxPeriod) + _, err = self.resource.LookupHistoricalByName(ctx, name, period, true, maxLookup) } else { - _, err = self.resource.LookupLatestByName(ctx, name, true, maxPeriod) + _, err = self.resource.LookupLatestByName(ctx, name, true, maxLookup) } if err != nil { return nil, nil, err diff --git a/swarm/api/http/server.go b/swarm/api/http/server.go index 3d3f05ada3..11e1c500bd 100644 --- a/swarm/api/http/server.go +++ b/swarm/api/http/server.go @@ -412,7 +412,7 @@ func (s *Server) handleGetResource(w http.ResponseWriter, r *Request, name strin log.Debug("handlegetdb", "name", name, "ruid", r.ruid) switch len(params) { case 0: - updateKey, data, err = s.api.ResourceLookup(r.Context(), name, 0, 0, 0) + updateKey, data, err = s.api.ResourceLookup(r.Context(), name, 0, 0, nil) case 2: version, err = strconv.ParseUint(params[1], 10, 32) if err != nil { @@ -422,13 +422,13 @@ func (s *Server) handleGetResource(w http.ResponseWriter, r *Request, name strin if err != nil { break } - updateKey, data, err = s.api.ResourceLookup(r.Context(), name, uint32(period), uint32(version), 0) + updateKey, data, err = s.api.ResourceLookup(r.Context(), name, uint32(period), uint32(version), nil) case 1: period, err = strconv.ParseUint(params[0], 10, 32) if err != nil { break } - updateKey, data, err = s.api.ResourceLookup(r.Context(), name, uint32(period), uint32(version), 0) + updateKey, data, err = s.api.ResourceLookup(r.Context(), name, uint32(period), uint32(version), nil) default: Respond(w, r, "invalid mutable resource request", http.StatusBadRequest) return diff --git a/swarm/storage/resource.go b/swarm/storage/resource.go index 15bcf81e1e..2d3c2de9bd 100644 --- a/swarm/storage/resource.go +++ b/swarm/storage/resource.go @@ -56,6 +56,11 @@ func NewResourceError(code int, s string) error { type Signature [signatureLength]byte +type ResourceLookupParams struct { + Limit bool + Max uint32 +} + type SignFunc func(common.Hash) (Signature, error) type nameHashFunc func(string) common.Hash @@ -164,16 +169,21 @@ type ResourceHandler struct { resourceLock sync.RWMutex nameHash nameHashFunc storeTimeout time.Duration - queryMaxPeriods uint + queryMaxPeriods *ResourceLookupParams } type ResourceHandlerParams struct { Validator ResourceValidator - QueryMaxPeriods uint + QueryMaxPeriods *ResourceLookupParams } // Create or open resource update chunk store func NewResourceHandler(hasher SwarmHasher, chunkStore ChunkStore, ethClient headerGetter, params *ResourceHandlerParams) (*ResourceHandler, error) { + if params.QueryMaxPeriods == nil { + params.QueryMaxPeriods = &ResourceLookupParams{ + Limit: false, + } + } rh := &ResourceHandler{ ChunkStore: chunkStore, ethClient: ethClient, @@ -330,16 +340,16 @@ func (self *ResourceHandler) NewResource(ctx context.Context, name string, frequ // If maxPeriod is -1, the default QueryMaxPeriod from ResourceHandlerParams will be used // if maxPeriod is 0, there will be no limit on period hops // if maxPeriod > 0, the given value will be the limit of period hops -func (self *ResourceHandler) LookupVersionByName(ctx context.Context, name string, period uint32, version uint32, refresh bool, maxPeriod int) (*resource, error) { - return self.LookupVersion(ctx, self.nameHash(name), name, period, version, refresh, maxPeriod) +func (self *ResourceHandler) LookupVersionByName(ctx context.Context, name string, period uint32, version uint32, refresh bool, maxLookup *ResourceLookupParams) (*resource, error) { + return self.LookupVersion(ctx, self.nameHash(name), name, period, version, refresh, maxLookup) } -func (self *ResourceHandler) LookupVersion(ctx context.Context, nameHash common.Hash, name string, period uint32, version uint32, refresh bool, maxPeriod int) (*resource, error) { +func (self *ResourceHandler) LookupVersion(ctx context.Context, nameHash common.Hash, name string, period uint32, version uint32, refresh bool, maxLookup *ResourceLookupParams) (*resource, error) { rsrc, err := self.loadResource(nameHash, name, refresh) if err != nil { return nil, err } - return self.lookup(rsrc, period, version, refresh, maxPeriod) + return self.lookup(rsrc, period, version, refresh, maxLookup) } // Retrieves the latest version of the resource update identified by `name` @@ -350,16 +360,16 @@ func (self *ResourceHandler) LookupVersion(ctx context.Context, nameHash common. // and returned. // // See also (*ResourceHandler).LookupVersion -func (self *ResourceHandler) LookupHistoricalByName(ctx context.Context, name string, period uint32, refresh bool, maxPeriod int) (*resource, error) { - return self.LookupHistorical(ctx, self.nameHash(name), name, period, refresh, maxPeriod) +func (self *ResourceHandler) LookupHistoricalByName(ctx context.Context, name string, period uint32, refresh bool, maxLookup *ResourceLookupParams) (*resource, error) { + return self.LookupHistorical(ctx, self.nameHash(name), name, period, refresh, maxLookup) } -func (self *ResourceHandler) LookupHistorical(ctx context.Context, nameHash common.Hash, name string, period uint32, refresh bool, maxPeriod int) (*resource, error) { +func (self *ResourceHandler) LookupHistorical(ctx context.Context, nameHash common.Hash, name string, period uint32, refresh bool, maxLookup *ResourceLookupParams) (*resource, error) { rsrc, err := self.loadResource(nameHash, name, refresh) if err != nil { return nil, err } - return self.lookup(rsrc, period, 0, refresh, maxPeriod) + return self.lookup(rsrc, period, 0, refresh, maxLookup) } // Retrieves the latest version of the resource update identified by `name` @@ -372,11 +382,11 @@ func (self *ResourceHandler) LookupHistorical(ctx context.Context, nameHash comm // Version iteration is done as in (*ResourceHandler).LookupHistorical // // See also (*ResourceHandler).LookupHistorical -func (self *ResourceHandler) LookupLatestByName(ctx context.Context, name string, refresh bool, maxPeriod int) (*resource, error) { - return self.LookupLatest(ctx, self.nameHash(name), name, refresh, maxPeriod) +func (self *ResourceHandler) LookupLatestByName(ctx context.Context, name string, refresh bool, maxLookup *ResourceLookupParams) (*resource, error) { + return self.LookupLatest(ctx, self.nameHash(name), name, refresh, maxLookup) } -func (self *ResourceHandler) LookupLatest(ctx context.Context, nameHash common.Hash, name string, refresh bool, maxPeriod int) (*resource, error) { +func (self *ResourceHandler) LookupLatest(ctx context.Context, nameHash common.Hash, name string, refresh bool, maxLookup *ResourceLookupParams) (*resource, error) { // get our blockheight at this time and the next block of the update period rsrc, err := self.loadResource(nameHash, name, refresh) @@ -388,11 +398,11 @@ func (self *ResourceHandler) LookupLatest(ctx context.Context, nameHash common.H return nil, err } nextperiod := getNextPeriod(rsrc.startBlock, currentblock, rsrc.frequency) - return self.lookup(rsrc, nextperiod, 0, refresh, maxPeriod) + return self.lookup(rsrc, nextperiod, 0, refresh, maxLookup) } // base code for public lookup methods -func (self *ResourceHandler) lookup(rsrc *resource, period uint32, version uint32, refresh bool, maxPeriod int) (*resource, error) { +func (self *ResourceHandler) lookup(rsrc *resource, period uint32, version uint32, refresh bool, maxLookup *ResourceLookupParams) (*resource, error) { if period == 0 { return nil, NewResourceError(ErrInvalidValue, "period must be >0") @@ -407,13 +417,13 @@ func (self *ResourceHandler) lookup(rsrc *resource, period uint32, version uint3 version = 1 } - hops := 0 - if maxPeriod < 0 { - maxPeriod = int(self.queryMaxPeriods) + var hops uint32 + if maxLookup == nil { + maxLookup = self.queryMaxPeriods } for period > 0 { - if hops > maxPeriod && maxPeriod > 0 { - return nil, NewResourceError(ErrPeriodDepth, fmt.Sprintf("Lookup exceeded max period hops (%d)", maxPeriod)) + if maxLookup.Limit && hops > maxLookup.Max { + return nil, NewResourceError(ErrPeriodDepth, fmt.Sprintf("Lookup exceeded max period hops (%d)", maxLookup.Max)) } key := self.resourceHash(period, version, rsrc.nameHash) chunk, err := self.Get(key) @@ -883,7 +893,7 @@ func isMultihash(data []byte) int { } // TODO: this should not be part of production code, but currently swarm/testutil/http.go needs it -func NewTestResourceHandler(datadir string, ethClient headerGetter, validator ResourceValidator, maxPeriod uint) (*ResourceHandler, error) { +func NewTestResourceHandler(datadir string, ethClient headerGetter, validator ResourceValidator, maxLimit *ResourceLookupParams) (*ResourceHandler, error) { path := filepath.Join(datadir, DbDirName) basekey := make([]byte, 32) hasher := MakeHashFunc(SHA3Hash) @@ -897,9 +907,14 @@ func NewTestResourceHandler(datadir string, ethClient headerGetter, validator Re DbStore: dbStore, } resourceChunkStore := NewResourceChunkStore(localStore, nil) + if maxLimit == nil { + maxLimit = &ResourceLookupParams{ + Limit: false, + } + } params := &ResourceHandlerParams{ Validator: validator, - QueryMaxPeriods: maxPeriod, + QueryMaxPeriods: maxLimit, } return NewResourceHandler(hasher, resourceChunkStore, ethClient, params) } diff --git a/swarm/storage/resource_test.go b/swarm/storage/resource_test.go index d4314f9ade..3b4b5d43d0 100644 --- a/swarm/storage/resource_test.go +++ b/swarm/storage/resource_test.go @@ -40,7 +40,6 @@ var ( func init() { var err error - //loglevel := flag.Int("loglevel", 3, "loglevel") flag.Parse() log.Root().SetHandler(log.CallerFileHandler(log.LvlFilterHandler(log.Lvl(*loglevel), log.StreamHandler(os.Stderr, log.TerminalFormat(true))))) safeName, err = ToSafeName(domainName) @@ -220,8 +219,14 @@ func TestResourceHandler(t *testing.T) { // it will match on second iteration startblocknumber + (resourceFrequency * 3) fwdBlocks(int(resourceFrequency*2)-1, backend) - rh2, err := NewTestResourceHandler(datadir, rh.ethClient, nil, 0) - _, err = rh2.LookupLatestByName(ctx, safeName, true, -1) + lookupParams := &ResourceLookupParams{ + Limit: false, + } + rh2, err := NewTestResourceHandler(datadir, rh.ethClient, nil, lookupParams) + if err != nil { + t.Fatal(err) + } + _, err = rh2.LookupLatestByName(ctx, safeName, true, nil) if err != nil { t.Fatal(err) } @@ -239,7 +244,7 @@ func TestResourceHandler(t *testing.T) { log.Debug("Latest lookup", "period", rh2.resources[safeName].lastPeriod, "version", rh2.resources[safeName].version, "data", rh2.resources[safeName].data) // specific block, latest version - rsrc, err := rh2.LookupHistoricalByName(ctx, safeName, 3, true, 0) + rsrc, err := rh2.LookupHistoricalByName(ctx, safeName, 3, true, lookupParams) if err != nil { t.Fatal(err) } @@ -250,7 +255,7 @@ func TestResourceHandler(t *testing.T) { log.Debug("Historical lookup", "period", rh2.resources[safeName].lastPeriod, "version", rh2.resources[safeName].version, "data", rh2.resources[safeName].data) // specific block, specific version - rsrc, err = rh2.LookupVersionByName(ctx, safeName, 3, 1, true, 0) + rsrc, err = rh2.LookupVersionByName(ctx, safeName, 3, 1, true, lookupParams) if err != nil { t.Fatal(err) } @@ -348,7 +353,7 @@ func TestResourceMultihash(t *testing.T) { rh.Close() // test with signed data - rh2, err := NewTestResourceHandler(datadir, rh.ethClient, validator, 0) + rh2, err := NewTestResourceHandler(datadir, rh.ethClient, validator, nil) if err != nil { t.Fatal(err) } @@ -479,7 +484,7 @@ func setupTest(backend headerGetter, validator ResourceValidator) (rh *ResourceH os.RemoveAll(datadir) } - rh, err = NewTestResourceHandler(datadir, backend, validator, 0) + rh, err = NewTestResourceHandler(datadir, backend, validator, &ResourceLookupParams{Limit: false}) return rh, datadir, signer, cleanF, nil } diff --git a/swarm/testutil/http.go b/swarm/testutil/http.go index eaf60b7ee9..2de0c0f966 100644 --- a/swarm/testutil/http.go +++ b/swarm/testutil/http.go @@ -70,7 +70,7 @@ func NewTestSwarmServer(t *testing.T) *TestSwarmServer { t.Fatal(err) } - rh, err := storage.NewTestResourceHandler(resourceDir, &fakeBackend{}, nil, 0) + rh, err := storage.NewTestResourceHandler(resourceDir, &fakeBackend{}, nil, &storage.ResourceLookupParams{Limit: false}) if err != nil { t.Fatal(err) }