forked from cerc-io/plugeth
swarm/storage/feeds: removed capital Feed throughout
This commit is contained in:
parent
68b8088cb9
commit
58c0879c2f
@ -14,7 +14,7 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
// Command feed allows the user to create and update signed Swarm Feeds
|
// Command feed allows the user to create and update signed Swarm feeds
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -145,7 +145,7 @@ func TestCLIFeedUpdate(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure the retrieved Feed is the same
|
// make sure the retrieved feed is the same
|
||||||
if request.Feed != feed {
|
if request.Feed != feed {
|
||||||
t.Fatalf("Expected feed to be: %s, got %s", feed, request.Feed)
|
t.Fatalf("Expected feed to be: %s, got %s", feed, request.Feed)
|
||||||
}
|
}
|
||||||
|
@ -355,8 +355,8 @@ func init() {
|
|||||||
Action: feedCreateManifest,
|
Action: feedCreateManifest,
|
||||||
CustomHelpTemplate: helpTemplate,
|
CustomHelpTemplate: helpTemplate,
|
||||||
Name: "create",
|
Name: "create",
|
||||||
Usage: "creates and publishes a new Feed manifest",
|
Usage: "creates and publishes a new feed manifest",
|
||||||
Description: `creates and publishes a new Feed manifest pointing to a specified user's updates about a particular topic.
|
Description: `creates and publishes a new feed manifest pointing to a specified user's updates about a particular topic.
|
||||||
The feed topic can be built in the following ways:
|
The feed topic can be built in the following ways:
|
||||||
* use --topic to set the topic to an arbitrary binary hex string.
|
* use --topic to set the topic to an arbitrary binary hex string.
|
||||||
* use --name to set the topic to a human-readable name.
|
* use --name to set the topic to a human-readable name.
|
||||||
@ -392,8 +392,8 @@ func init() {
|
|||||||
Action: feedInfo,
|
Action: feedInfo,
|
||||||
CustomHelpTemplate: helpTemplate,
|
CustomHelpTemplate: helpTemplate,
|
||||||
Name: "info",
|
Name: "info",
|
||||||
Usage: "obtains information about an existing Swarm Feed",
|
Usage: "obtains information about an existing Swarm feed",
|
||||||
Description: `obtains information about an existing Swarm Feed
|
Description: `obtains information about an existing Swarm feed
|
||||||
The topic can be specified directly with the --topic flag as an hex string
|
The topic can be specified directly with the --topic flag as an hex string
|
||||||
If no topic is specified, the default topic (zero) will be used
|
If no topic is specified, the default topic (zero) will be used
|
||||||
The --name flag can be used to specify subtopics with a specific name.
|
The --name flag can be used to specify subtopics with a specific name.
|
||||||
|
@ -404,7 +404,7 @@ func (a *API) Get(ctx context.Context, decrypt DecryptFunc, manifestAddr storage
|
|||||||
return a.Get(ctx, decrypt, adr, entry.Path)
|
return a.Get(ctx, decrypt, adr, entry.Path)
|
||||||
}
|
}
|
||||||
|
|
||||||
// we need to do some extra work if this is a Feed manifest
|
// we need to do some extra work if this is a Swarm feed manifest
|
||||||
if entry.ContentType == FeedContentType {
|
if entry.ContentType == FeedContentType {
|
||||||
if entry.Feed == nil {
|
if entry.Feed == nil {
|
||||||
return reader, mimeType, status, nil, fmt.Errorf("Cannot decode Feed in manifest")
|
return reader, mimeType, status, nil, fmt.Errorf("Cannot decode Feed in manifest")
|
||||||
@ -957,7 +957,7 @@ func (a *API) BuildDirectoryTree(ctx context.Context, mhash string, nameresolver
|
|||||||
return addr, manifestEntryMap, nil
|
return addr, manifestEntryMap, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// FeedsLookup finds Swarm Feeds Updates at specific points in time, or the latest update
|
// FeedsLookup finds Swarm feeds updates at specific points in time, or the latest update
|
||||||
func (a *API) FeedsLookup(ctx context.Context, query *feeds.Query) ([]byte, error) {
|
func (a *API) FeedsLookup(ctx context.Context, query *feeds.Query) ([]byte, error) {
|
||||||
_, err := a.feeds.Lookup(ctx, query)
|
_, err := a.feeds.Lookup(ctx, query)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -971,17 +971,17 @@ func (a *API) FeedsLookup(ctx context.Context, query *feeds.Query) ([]byte, erro
|
|||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// FeedsNewRequest creates a Request object to update a specific Feed
|
// FeedsNewRequest creates a Request object to update a specific feed
|
||||||
func (a *API) FeedsNewRequest(ctx context.Context, feed *feeds.Feed) (*feeds.Request, error) {
|
func (a *API) FeedsNewRequest(ctx context.Context, feed *feeds.Feed) (*feeds.Request, error) {
|
||||||
return a.feeds.NewRequest(ctx, feed)
|
return a.feeds.NewRequest(ctx, feed)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FeedsUpdate publishes a new update on the given Feed
|
// FeedsUpdate publishes a new update on the given feed
|
||||||
func (a *API) FeedsUpdate(ctx context.Context, request *feeds.Request) (storage.Address, error) {
|
func (a *API) FeedsUpdate(ctx context.Context, request *feeds.Request) (storage.Address, error) {
|
||||||
return a.feeds.Update(ctx, request)
|
return a.feeds.Update(ctx, request)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FeedsHashSize returned the size of the digest produced by Swarm Feeds' hashing function
|
// FeedsHashSize returned the size of the digest produced by Swarm feeds' hashing function
|
||||||
func (a *API) FeedsHashSize() int {
|
func (a *API) FeedsHashSize() int {
|
||||||
return a.feeds.HashSize
|
return a.feeds.HashSize
|
||||||
}
|
}
|
||||||
@ -992,7 +992,7 @@ var ErrCannotLoadFeedManifest = errors.New("Cannot load feed manifest")
|
|||||||
// ErrNotAFeedManifest is returned when the address provided returned something other than a valid manifest
|
// ErrNotAFeedManifest is returned when the address provided returned something other than a valid manifest
|
||||||
var ErrNotAFeedManifest = errors.New("Not a feed manifest")
|
var ErrNotAFeedManifest = errors.New("Not a feed manifest")
|
||||||
|
|
||||||
// ResolveFeedManifest retrieves the Feed manifest for the given address, and returns the referenced Feed.
|
// ResolveFeedManifest retrieves the Swarm feed manifest for the given address, and returns the referenced Feed.
|
||||||
func (a *API) ResolveFeedManifest(ctx context.Context, addr storage.Address) (*feeds.Feed, error) {
|
func (a *API) ResolveFeedManifest(ctx context.Context, addr storage.Address) (*feeds.Feed, error) {
|
||||||
trie, err := loadManifest(ctx, a.fileStore, addr, nil, NOOPDecrypt)
|
trie, err := loadManifest(ctx, a.fileStore, addr, nil, NOOPDecrypt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1007,15 +1007,15 @@ func (a *API) ResolveFeedManifest(ctx context.Context, addr storage.Address) (*f
|
|||||||
return entry.Feed, nil
|
return entry.Feed, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrCannotResolveFeedURI is returned when the ENS resolver is not able to translate a name to a Feed
|
// ErrCannotResolveFeedURI is returned when the ENS resolver is not able to translate a name to a Swarm feed
|
||||||
var ErrCannotResolveFeedURI = errors.New("Cannot resolve Feed URI")
|
var ErrCannotResolveFeedURI = errors.New("Cannot resolve Feed URI")
|
||||||
|
|
||||||
// ErrCannotResolveFeed is returned when values provided are not enough or invalid to recreate a
|
// ErrCannotResolveFeed is returned when values provided are not enough or invalid to recreate a
|
||||||
// Feed out of them.
|
// feed out of them.
|
||||||
var ErrCannotResolveFeed = errors.New("Cannot resolve Feed")
|
var ErrCannotResolveFeed = errors.New("Cannot resolve Feed")
|
||||||
|
|
||||||
// ResolveFeed attempts to extract Feed information out of the manifest, if provided
|
// ResolveFeed attempts to extract feed information out of the manifest, if provided
|
||||||
// If not, it attempts to extract the Feed out of a set of key-value pairs
|
// If not, it attempts to extract the feed out of a set of key-value pairs
|
||||||
func (a *API) ResolveFeed(ctx context.Context, uri *URI, values feeds.Values) (*feeds.Feed, error) {
|
func (a *API) ResolveFeed(ctx context.Context, uri *URI, values feeds.Values) (*feeds.Feed, error) {
|
||||||
var feed *feeds.Feed
|
var feed *feeds.Feed
|
||||||
var err error
|
var err error
|
||||||
@ -1029,7 +1029,7 @@ func (a *API) ResolveFeed(ctx context.Context, uri *URI, values feeds.Values) (*
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the Feed from the manifest
|
// get the Swarm feed from the manifest
|
||||||
feed, err = a.ResolveFeedManifest(ctx, manifestAddr)
|
feed, err = a.ResolveFeedManifest(ctx, manifestAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -604,9 +604,9 @@ func (c *Client) MultipartUpload(hash string, uploader Uploader) (string, error)
|
|||||||
// ErrNoFeedUpdatesFound is returned when Swarm cannot find updates of the given feed
|
// ErrNoFeedUpdatesFound is returned when Swarm cannot find updates of the given feed
|
||||||
var ErrNoFeedUpdatesFound = errors.New("No updates found for this feed")
|
var ErrNoFeedUpdatesFound = errors.New("No updates found for this feed")
|
||||||
|
|
||||||
// CreateFeedWithManifest creates a Feed Manifest, initializing it with the provided
|
// CreateFeedWithManifest creates a feed manifest, initializing it with the provided
|
||||||
// data
|
// data
|
||||||
// Returns the resulting Feed Manifest address that you can use to include in an ENS Resolver (setContent)
|
// Returns the resulting feed manifest address that you can use to include in an ENS Resolver (setContent)
|
||||||
// or reference future updates (Client.UpdateFeed)
|
// or reference future updates (Client.UpdateFeed)
|
||||||
func (c *Client) CreateFeedWithManifest(request *feeds.Request) (string, error) {
|
func (c *Client) CreateFeedWithManifest(request *feeds.Request) (string, error) {
|
||||||
responseStream, err := c.updateFeed(request, true)
|
responseStream, err := c.updateFeed(request, true)
|
||||||
@ -669,7 +669,7 @@ func (c *Client) QueryFeed(query *feeds.Query, manifestAddressOrDomain string) (
|
|||||||
// queryFeed returns a byte stream with the raw content of the feed update
|
// queryFeed returns a byte stream with the raw content of the feed update
|
||||||
// manifestAddressOrDomain is the address you obtained in CreateFeedWithManifest or an ENS domain whose Resolver
|
// manifestAddressOrDomain is the address you obtained in CreateFeedWithManifest or an ENS domain whose Resolver
|
||||||
// points to that address
|
// points to that address
|
||||||
// meta set to true will instruct the node return Feed metainformation instead
|
// meta set to true will instruct the node return feed metainformation instead
|
||||||
func (c *Client) queryFeed(query *feeds.Query, manifestAddressOrDomain string, meta bool) (io.ReadCloser, error) {
|
func (c *Client) queryFeed(query *feeds.Query, manifestAddressOrDomain string, meta bool) (io.ReadCloser, error) {
|
||||||
URL, err := url.Parse(c.Gateway)
|
URL, err := url.Parse(c.Gateway)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -706,7 +706,7 @@ func (c *Client) queryFeed(query *feeds.Query, manifestAddressOrDomain string, m
|
|||||||
return res.Body, nil
|
return res.Body, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetFeedRequest returns a structure that describes the referenced Feed status
|
// GetFeedRequest returns a structure that describes the referenced feed status
|
||||||
// manifestAddressOrDomain is the address you obtained in CreateFeedWithManifest or an ENS domain whose Resolver
|
// manifestAddressOrDomain is the address you obtained in CreateFeedWithManifest or an ENS domain whose Resolver
|
||||||
// points to that address
|
// points to that address
|
||||||
func (c *Client) GetFeedRequest(query *feeds.Query, manifestAddressOrDomain string) (*feeds.Request, error) {
|
func (c *Client) GetFeedRequest(query *feeds.Query, manifestAddressOrDomain string) (*feeds.Request, error) {
|
||||||
|
@ -518,7 +518,7 @@ func (s *Server) HandlePostFeed(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
// the key to the manifest will be passed back to the client
|
// the key to the manifest will be passed back to the client
|
||||||
// the client can access the Feed directly through its Feed member
|
// the client can access the feed directly through its Feed member
|
||||||
// the manifest key can be set as content in the resolver of the ENS name
|
// the manifest key can be set as content in the resolver of the ENS name
|
||||||
outdata, err := json.Marshal(m)
|
outdata, err := json.Marshal(m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -531,7 +531,7 @@ func (s *Server) HandlePostFeed(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandleGetFeed retrieves Swarm Feeds updates:
|
// HandleGetFeed retrieves Swarm feeds updates:
|
||||||
// bzz-feed://<manifest address or ENS name> - get latest feed update, given a manifest address
|
// bzz-feed://<manifest address or ENS name> - get latest feed update, given a manifest address
|
||||||
// - or -
|
// - or -
|
||||||
// specify user + topic (optional), subtopic name (optional) directly, without manifest:
|
// specify user + topic (optional), subtopic name (optional) directly, without manifest:
|
||||||
|
@ -165,7 +165,7 @@ func TestBzzFeedMultihash(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test Swarm Feeds using the raw update methods
|
// Test Swarm feeds using the raw update methods
|
||||||
func TestBzzFeed(t *testing.T) {
|
func TestBzzFeed(t *testing.T) {
|
||||||
srv := testutil.NewTestSwarmServer(t, serverFunc, nil)
|
srv := testutil.NewTestSwarmServer(t, serverFunc, nil)
|
||||||
signer, _ := newTestSigner()
|
signer, _ := newTestSigner()
|
||||||
@ -305,7 +305,7 @@ func TestBzzFeed(t *testing.T) {
|
|||||||
srv.CurrentTime++
|
srv.CurrentTime++
|
||||||
log.Info("update 2")
|
log.Info("update 2")
|
||||||
|
|
||||||
// 1.- get metadata about this Feed
|
// 1.- get metadata about this feed
|
||||||
testBzzResUrl = fmt.Sprintf("%s/bzz-feed:/%s/", srv.URL, correctManifestAddrHex)
|
testBzzResUrl = fmt.Sprintf("%s/bzz-feed:/%s/", srv.URL, correctManifestAddrHex)
|
||||||
resp, err = http.Get(testBzzResUrl + "?meta=1")
|
resp, err = http.Get(testBzzResUrl + "?meta=1")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -80,7 +80,7 @@ func (a *API) NewManifest(ctx context.Context, toEncrypt bool) (storage.Address,
|
|||||||
return addr, err
|
return addr, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Manifest hack for supporting Feeds from the bzz: scheme
|
// Manifest hack for supporting Swarm feeds from the bzz: scheme
|
||||||
// see swarm/api/api.go:API.Get() for more information
|
// see swarm/api/api.go:API.Get() for more information
|
||||||
func (a *API) NewFeedManifest(ctx context.Context, feed *feeds.Feed) (storage.Address, error) {
|
func (a *API) NewFeedManifest(ctx context.Context, feed *feeds.Feed) (storage.Address, error) {
|
||||||
var manifest Manifest
|
var manifest Manifest
|
||||||
|
@ -37,7 +37,7 @@ Using the streamer logic, various stream types are easy to implement:
|
|||||||
* live session syncing
|
* live session syncing
|
||||||
* historical syncing
|
* historical syncing
|
||||||
* simple retrieve requests and deliveries
|
* simple retrieve requests and deliveries
|
||||||
* Swarm Feeds streams
|
* swarm feeds streams
|
||||||
* receipting for finger pointing
|
* receipting for finger pointing
|
||||||
|
|
||||||
## Syncing
|
## Syncing
|
||||||
@ -57,7 +57,7 @@ receipts for a deleted chunk easily to refute their challenge.
|
|||||||
- syncing should be resilient to cut connections, metadata should be persisted that
|
- syncing should be resilient to cut connections, metadata should be persisted that
|
||||||
keep track of syncing state across sessions, historical syncing state should survive restart
|
keep track of syncing state across sessions, historical syncing state should survive restart
|
||||||
- extra data structures to support syncing should be kept at minimum
|
- extra data structures to support syncing should be kept at minimum
|
||||||
- syncing is organized separately for chunk types (Swarm Feed Updates v regular content chunk)
|
- syncing is not organized separately for chunk types (Swarm feed updates v regular content chunk)
|
||||||
- various types of streams should have common logic abstracted
|
- various types of streams should have common logic abstracted
|
||||||
|
|
||||||
Syncing is now entirely mediated by the localstore, ie., no processes or memory leaks due to network contention.
|
Syncing is now entirely mediated by the localstore, ie., no processes or memory leaks due to network contention.
|
||||||
|
@ -30,7 +30,7 @@ const (
|
|||||||
defaultRetrieveTimeout = 100 * time.Millisecond
|
defaultRetrieveTimeout = 100 * time.Millisecond
|
||||||
)
|
)
|
||||||
|
|
||||||
// cacheEntry caches the last known update of a specific Feed.
|
// cacheEntry caches the last known update of a specific Swarm feed.
|
||||||
type cacheEntry struct {
|
type cacheEntry struct {
|
||||||
Update
|
Update
|
||||||
*bytes.Reader
|
*bytes.Reader
|
||||||
@ -42,7 +42,7 @@ func (r *cacheEntry) Size(ctx context.Context, _ chan bool) (int64, error) {
|
|||||||
return int64(len(r.Update.data)), nil
|
return int64(len(r.Update.data)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//returns the Feed's topic
|
//returns the feed's topic
|
||||||
func (r *cacheEntry) Topic() Topic {
|
func (r *cacheEntry) Topic() Topic {
|
||||||
return r.Feed.Topic
|
return r.Feed.Topic
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ const (
|
|||||||
ErrCnt
|
ErrCnt
|
||||||
)
|
)
|
||||||
|
|
||||||
// Error is a the typed error object used for Swarm Feeds
|
// Error is a the typed error object used for Swarm feeds
|
||||||
type Error struct {
|
type Error struct {
|
||||||
code int
|
code int
|
||||||
err string
|
err string
|
||||||
@ -52,7 +52,7 @@ func (e *Error) Code() int {
|
|||||||
return e.code
|
return e.code
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewError creates a new Swarm Feeds Error object with the specified code and custom error message
|
// NewError creates a new Swarm feeds Error object with the specified code and custom error message
|
||||||
func NewError(code int, s string) error {
|
func NewError(code int, s string) error {
|
||||||
if code < 0 || code >= ErrCnt {
|
if code < 0 || code >= ErrCnt {
|
||||||
panic("no such error code!")
|
panic("no such error code!")
|
||||||
|
@ -25,7 +25,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/swarm/storage"
|
"github.com/ethereum/go-ethereum/swarm/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Feed represents a particular user's stream of updates on a Topic
|
// Feed represents a particular user's stream of updates on a topic
|
||||||
type Feed struct {
|
type Feed struct {
|
||||||
Topic Topic `json:"topic"`
|
Topic Topic `json:"topic"`
|
||||||
User common.Address `json:"user"`
|
User common.Address `json:"user"`
|
||||||
@ -48,10 +48,10 @@ func (f *Feed) mapKey() uint64 {
|
|||||||
return *(*uint64)(unsafe.Pointer(&hash[0]))
|
return *(*uint64)(unsafe.Pointer(&hash[0]))
|
||||||
}
|
}
|
||||||
|
|
||||||
// binaryPut serializes this Feed instance into the provided slice
|
// binaryPut serializes this feed instance into the provided slice
|
||||||
func (f *Feed) binaryPut(serializedData []byte) error {
|
func (f *Feed) binaryPut(serializedData []byte) error {
|
||||||
if len(serializedData) != feedLength {
|
if len(serializedData) != feedLength {
|
||||||
return NewErrorf(ErrInvalidValue, "Incorrect slice size to serialize Feed. Expected %d, got %d", feedLength, len(serializedData))
|
return NewErrorf(ErrInvalidValue, "Incorrect slice size to serialize feed. Expected %d, got %d", feedLength, len(serializedData))
|
||||||
}
|
}
|
||||||
var cursor int
|
var cursor int
|
||||||
copy(serializedData[cursor:cursor+TopicLength], f.Topic[:TopicLength])
|
copy(serializedData[cursor:cursor+TopicLength], f.Topic[:TopicLength])
|
||||||
@ -71,7 +71,7 @@ func (f *Feed) binaryLength() int {
|
|||||||
// binaryGet restores the current instance from the information contained in the passed slice
|
// binaryGet restores the current instance from the information contained in the passed slice
|
||||||
func (f *Feed) binaryGet(serializedData []byte) error {
|
func (f *Feed) binaryGet(serializedData []byte) error {
|
||||||
if len(serializedData) != feedLength {
|
if len(serializedData) != feedLength {
|
||||||
return NewErrorf(ErrInvalidValue, "Incorrect slice size to read Feed. Expected %d, got %d", feedLength, len(serializedData))
|
return NewErrorf(ErrInvalidValue, "Incorrect slice size to read feed. Expected %d, got %d", feedLength, len(serializedData))
|
||||||
}
|
}
|
||||||
|
|
||||||
var cursor int
|
var cursor int
|
||||||
@ -84,7 +84,7 @@ func (f *Feed) binaryGet(serializedData []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hex serializes the Feed to a hex string
|
// Hex serializes the feed to a hex string
|
||||||
func (f *Feed) Hex() string {
|
func (f *Feed) Hex() string {
|
||||||
serializedData := make([]byte, feedLength)
|
serializedData := make([]byte, feedLength)
|
||||||
f.binaryPut(serializedData)
|
f.binaryPut(serializedData)
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
// You should have received a copy of the GNU Lesser General Public License
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
// Handler is the API for Feeds
|
// Handler is the API for feeds
|
||||||
// It enables creating, updating, syncing and retrieving feed updates and their data
|
// It enables creating, updating, syncing and retrieving feed updates and their data
|
||||||
package feeds
|
package feeds
|
||||||
|
|
||||||
@ -57,7 +57,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewHandler creates a new Swarm Feeds API
|
// NewHandler creates a new Swarm feeds API
|
||||||
func NewHandler(params *HandlerParams) *Handler {
|
func NewHandler(params *HandlerParams) *Handler {
|
||||||
fh := &Handler{
|
fh := &Handler{
|
||||||
cache: make(map[uint64]*cacheEntry),
|
cache: make(map[uint64]*cacheEntry),
|
||||||
@ -74,7 +74,7 @@ func NewHandler(params *HandlerParams) *Handler {
|
|||||||
return fh
|
return fh
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetStore sets the store backend for the Swarm Feeds API
|
// SetStore sets the store backend for the Swarm feeds API
|
||||||
func (h *Handler) SetStore(store *storage.NetStore) {
|
func (h *Handler) SetStore(store *storage.NetStore) {
|
||||||
h.chunkStore = store
|
h.chunkStore = store
|
||||||
}
|
}
|
||||||
@ -110,7 +110,7 @@ func (h *Handler) Validate(chunkAddr storage.Address, data []byte) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetContent retrieves the data payload of the last synced update of the Feed
|
// GetContent retrieves the data payload of the last synced update of the feed
|
||||||
func (h *Handler) GetContent(feed *Feed) (storage.Address, []byte, error) {
|
func (h *Handler) GetContent(feed *Feed) (storage.Address, []byte, error) {
|
||||||
if feed == nil {
|
if feed == nil {
|
||||||
return nil, nil, NewError(ErrInvalidValue, "feed is nil")
|
return nil, nil, NewError(ErrInvalidValue, "feed is nil")
|
||||||
@ -240,7 +240,7 @@ func (h *Handler) updateCache(request *Request) (*cacheEntry, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update publishes a feed update
|
// Update publishes a feed update
|
||||||
// Note that a Feed update cannot span chunks, and thus has a MAX NET LENGTH 4096, INCLUDING update header data and signature.
|
// Note that a feed update cannot span chunks, and thus has a MAX NET LENGTH 4096, INCLUDING update header data and signature.
|
||||||
// This results in a max payload of `maxUpdateDataLength` (check update.go for more details)
|
// This results in a max payload of `maxUpdateDataLength` (check update.go for more details)
|
||||||
// An error will be returned if the total length of the chunk payload will exceed this limit.
|
// An error will be returned if the total length of the chunk payload will exceed this limit.
|
||||||
// Update can only check if the caller is trying to overwrite the very last known version, otherwise it just puts the update
|
// Update can only check if the caller is trying to overwrite the very last known version, otherwise it just puts the update
|
||||||
@ -286,7 +286,7 @@ func (h *Handler) get(feed *Feed) *cacheEntry {
|
|||||||
return feedUpdate
|
return feedUpdate
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets the feed update cache value for the given Feed
|
// Sets the feed update cache value for the given feed
|
||||||
func (h *Handler) set(feed *Feed, feedUpdate *cacheEntry) {
|
func (h *Handler) set(feed *Feed, feedUpdate *cacheEntry) {
|
||||||
mapKey := feed.mapKey()
|
mapKey := feed.mapKey()
|
||||||
h.cacheLock.Lock()
|
h.cacheLock.Lock()
|
||||||
|
@ -89,11 +89,11 @@ func TestFeedsHandler(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer teardownTest()
|
defer teardownTest()
|
||||||
|
|
||||||
// create a new Feed
|
// create a new feed
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
topic, _ := NewTopic("Mess with Swarm Feeds code and see what ghost catches you", nil)
|
topic, _ := NewTopic("Mess with Swarm feeds code and see what ghost catches you", nil)
|
||||||
feed := Feed{
|
feed := Feed{
|
||||||
Topic: topic,
|
Topic: topic,
|
||||||
User: signer.Address(),
|
User: signer.Address(),
|
||||||
@ -266,7 +266,7 @@ func TestSparseUpdates(t *testing.T) {
|
|||||||
defer teardownTest()
|
defer teardownTest()
|
||||||
defer os.RemoveAll(datadir)
|
defer os.RemoveAll(datadir)
|
||||||
|
|
||||||
// create a new Feed
|
// create a new feed
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
topic, _ := NewTopic("Very slow updates", nil)
|
topic, _ := NewTopic("Very slow updates", nil)
|
||||||
@ -348,7 +348,7 @@ func TestValidator(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer teardownTest()
|
defer teardownTest()
|
||||||
|
|
||||||
// create new Feed
|
// create new feed
|
||||||
topic, _ := NewTopic(subtopicName, nil)
|
topic, _ := NewTopic(subtopicName, nil)
|
||||||
feed := Feed{
|
feed := Feed{
|
||||||
Topic: topic,
|
Topic: topic,
|
||||||
@ -382,7 +382,7 @@ func TestValidator(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// tests that the content address validator correctly checks the data
|
// tests that the content address validator correctly checks the data
|
||||||
// tests that Feed update chunks are passed through content address validator
|
// tests that feed update chunks are passed through content address validator
|
||||||
// there is some redundancy in this test as it also tests content addressed chunks,
|
// there is some redundancy in this test as it also tests content addressed chunks,
|
||||||
// which should be evaluated as invalid chunks by this validator
|
// which should be evaluated as invalid chunks by this validator
|
||||||
func TestValidatorInStore(t *testing.T) {
|
func TestValidatorInStore(t *testing.T) {
|
||||||
@ -409,7 +409,7 @@ func TestValidatorInStore(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// set up Swarm Feeds handler and add is as a validator to the localstore
|
// set up Swarm feeds handler and add is as a validator to the localstore
|
||||||
fhParams := &HandlerParams{}
|
fhParams := &HandlerParams{}
|
||||||
fh := NewHandler(fhParams)
|
fh := NewHandler(fhParams)
|
||||||
store.Validators = append(store.Validators, fh)
|
store.Validators = append(store.Validators, fh)
|
||||||
@ -463,7 +463,7 @@ func TestValidatorInStore(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// create rpc and Feeds Handler
|
// create rpc and feeds Handler
|
||||||
func setupTest(timeProvider timestampProvider, signer Signer) (fh *TestHandler, datadir string, teardown func(), err error) {
|
func setupTest(timeProvider timestampProvider, signer Signer) (fh *TestHandler, datadir string, teardown func(), err error) {
|
||||||
|
|
||||||
var fsClean func()
|
var fsClean func()
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Package lookup defines Feed lookup algorithms and provides tools to place updates
|
Package lookup defines feed lookup algorithms and provides tools to place updates
|
||||||
so they can be found
|
so they can be found
|
||||||
*/
|
*/
|
||||||
package lookup
|
package lookup
|
||||||
|
@ -27,7 +27,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/swarm/storage/feeds/lookup"
|
"github.com/ethereum/go-ethereum/swarm/storage/feeds/lookup"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request represents a request to sign or signed Feed Update message
|
// Request represents a request to sign or signed feed update message
|
||||||
type Request struct {
|
type Request struct {
|
||||||
Update // actual content that will be put on the chunk, less signature
|
Update // actual content that will be put on the chunk, less signature
|
||||||
Signature *Signature
|
Signature *Signature
|
||||||
|
@ -47,7 +47,7 @@ func areEqualJSON(s1, s2 string) (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TestEncodingDecodingUpdateRequests ensures that requests are serialized properly
|
// TestEncodingDecodingUpdateRequests ensures that requests are serialized properly
|
||||||
// while also checking cryptographically that only the owner of a Feed can update it.
|
// while also checking cryptographically that only the owner of a feed can update it.
|
||||||
func TestEncodingDecodingUpdateRequests(t *testing.T) {
|
func TestEncodingDecodingUpdateRequests(t *testing.T) {
|
||||||
|
|
||||||
charlie := newCharlieSigner() //Charlie
|
charlie := newCharlieSigner() //Charlie
|
||||||
@ -136,7 +136,7 @@ func TestEncodingDecodingUpdateRequests(t *testing.T) {
|
|||||||
t.Fatal("Expected DecodeUpdateRequest to fail when trying to interpret a corrupt message with an invalid signature")
|
t.Fatal("Expected DecodeUpdateRequest to fail when trying to interpret a corrupt message with an invalid signature")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now imagine Bob wants to create an update of his own about the same Feed,
|
// Now imagine Bob wants to create an update of his own about the same feed,
|
||||||
// signing a message with his private key
|
// signing a message with his private key
|
||||||
if err := request.Sign(bob); err != nil {
|
if err := request.Sign(bob); err != nil {
|
||||||
t.Fatalf("Error signing: %s", err)
|
t.Fatalf("Error signing: %s", err)
|
||||||
@ -228,7 +228,7 @@ func TestUpdateChunkSerializationErrorChecking(t *testing.T) {
|
|||||||
var recovered Request
|
var recovered Request
|
||||||
recovered.fromChunk(chunk.Address(), chunk.Data())
|
recovered.fromChunk(chunk.Address(), chunk.Data())
|
||||||
if !reflect.DeepEqual(recovered, r) {
|
if !reflect.DeepEqual(recovered, r) {
|
||||||
t.Fatal("Expected recovered Request update to equal the original one")
|
t.Fatal("Expected recovered feed update request to equal the original one")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -248,7 +248,7 @@ func TestReverse(t *testing.T) {
|
|||||||
// signer containing private key
|
// signer containing private key
|
||||||
signer := newAliceSigner()
|
signer := newAliceSigner()
|
||||||
|
|
||||||
// set up rpc and create Feeds handler
|
// set up rpc and create feeds handler
|
||||||
_, _, teardownTest, err := setupTest(timeProvider, signer)
|
_, _, teardownTest, err := setupTest(timeProvider, signer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -28,7 +28,7 @@ const signatureLength = 65
|
|||||||
// Signature is an alias for a static byte array with the size of a signature
|
// Signature is an alias for a static byte array with the size of a signature
|
||||||
type Signature [signatureLength]byte
|
type Signature [signatureLength]byte
|
||||||
|
|
||||||
// Signer signs Feed update payloads
|
// Signer signs feed update payloads
|
||||||
type Signer interface {
|
type Signer interface {
|
||||||
Sign(common.Hash) (Signature, error)
|
Sign(common.Hash) (Signature, error)
|
||||||
Address() common.Address
|
Address() common.Address
|
||||||
@ -65,7 +65,7 @@ func (s *GenericSigner) Address() common.Address {
|
|||||||
return s.address
|
return s.address
|
||||||
}
|
}
|
||||||
|
|
||||||
// getUserAddr extracts the address of the Feed update signer
|
// getUserAddr extracts the address of the feed update signer
|
||||||
func getUserAddr(digest common.Hash, signature Signature) (common.Address, error) {
|
func getUserAddr(digest common.Hash, signature Signature) (common.Address, error) {
|
||||||
pub, err := crypto.SigToPub(digest.Bytes(), signature[:])
|
pub, err := crypto.SigToPub(digest.Bytes(), signature[:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -30,7 +30,7 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// tests that the content address validator correctly checks the data
|
// tests that the content address validator correctly checks the data
|
||||||
// tests that Feed update chunks are passed through content address validator
|
// tests that feed update chunks are passed through content address validator
|
||||||
// the test checking the resouce update validator internal correctness is found in storage/feeds/handler_test.go
|
// the test checking the resouce update validator internal correctness is found in storage/feeds/handler_test.go
|
||||||
func TestValidator(t *testing.T) {
|
func TestValidator(t *testing.T) {
|
||||||
// set up localstore
|
// set up localstore
|
||||||
|
@ -48,7 +48,7 @@ func NewTestSwarmServer(t *testing.T, serverFunc func(*api.API) TestServer, reso
|
|||||||
}
|
}
|
||||||
fileStore := storage.NewFileStore(localStore, storage.NewFileStoreParams())
|
fileStore := storage.NewFileStore(localStore, storage.NewFileStoreParams())
|
||||||
|
|
||||||
// Swarm Feeds test setup
|
// Swarm feeds test setup
|
||||||
feedsDir, err := ioutil.TempDir("", "swarm-feeds-test")
|
feedsDir, err := ioutil.TempDir("", "swarm-feeds-test")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
Loading…
Reference in New Issue
Block a user