Documentation ¶
Overview ¶
Package mru defines Mutable resource updates. A Mutable Resource is an entity which allows updates to a resource without resorting to ENS on each update. The update scheme is built on swarm chunks with chunk keys following a predictable, versionable pattern.
Updates are defined to be periodic in nature, where the update frequency is expressed in seconds.
The root entry of a mutable resource is tied to a unique identifier that is deterministically generated out of the metadata content that describes the resource. This metadata includes a user-defined resource name, a resource start time that indicates when the resource becomes valid, the frequency in seconds with which the resource is expected to be updated, both of which are stored as little-endian uint64 values in the database (for a total of 16 bytes). It also contains the owner's address (ownerAddr) This MRU info is stored in a separate content-addressed chunk (call it the metadata chunk), with the following layout:
(00|length|startTime|frequency|name|ownerAddr)
(The two first zero-value bytes are used for disambiguation by the chunk validator, and update chunk will always have a value > 0 there.)
Each metadata chunk is identified by its rootAddr, calculated as follows: metaHash=H(len(metadata), startTime, frequency,name) rootAddr = H(metaHash, ownerAddr). where H is the SHA3 hash function This scheme effectively locks the root chunk so that only the owner of the private key that ownerAddr was derived from can sign updates.
The root entry tells the requester from when the mutable resource was first added (Unix time in seconds) and in which moments to look for the actual updates. Thus, a resource update for identifier "føø.bar" starting at unix time 1528800000 with frequency 300 (every 5 mins) will have updates on 1528800300, 1528800600, 1528800900 and so on.
Actual data updates are also made in the form of swarm chunks. The keys of the updates are the hash of a concatenation of properties as follows:
updateAddr = H(period, version, rootAddr) where H is the SHA3 hash function The period is (currentTime - startTime) / frequency
Using our previous example, this means that a period 3 will happen when the clock hits 1528800900
If more than one update is made in the same period, incremental version numbers are used successively.
A user looking up a resource would only need to know the rootAddr in order to get the versions ¶
the resource update data is: resourcedata = headerlength|period|version|rootAddr|flags|metaHash where flags is a 1-byte flags field. Flag 0 is set to 1 to indicate multihash
the full update data that goes in the chunk payload is: resourcedata|sign(resourcedata)
headerlength is a 16 bit value containing the byte length of period|version|rootAddr|flags|metaHash
Handler is the API for Mutable Resources It enables creating, updating, syncing and retrieving resources and their update data
Index ¶
- Constants
- Variables
- func NewError(code int, s string) error
- func NewErrorf(code int, format string, args ...interface{}) error
- type DefaultTimestampProvider
- type Error
- type GenericSigner
- type Handler
- func (h *Handler) GetContent(rootAddr storage.Address) (storage.Address, []byte, error)
- func (h *Handler) GetLastPeriod(rootAddr storage.Address) (uint32, error)
- func (h *Handler) GetVersion(rootAddr storage.Address) (uint32, error)
- func (h *Handler) Load(ctx context.Context, rootAddr storage.Address) (*resource, error)
- func (h *Handler) Lookup(ctx context.Context, params *LookupParams) (*resource, error)
- func (h *Handler) LookupPrevious(ctx context.Context, params *LookupParams) (*resource, error)
- func (h *Handler) New(ctx context.Context, request *Request) error
- func (h *Handler) NewUpdateRequest(ctx context.Context, rootAddr storage.Address) (updateRequest *Request, err error)
- func (h *Handler) SetStore(store *storage.NetStore)
- func (h *Handler) Update(ctx context.Context, r *SignedResourceUpdate) (storage.Address, error)
- func (h *Handler) Validate(chunkAddr storage.Address, data []byte) bool
- type HandlerParams
- type LookupParams
- func LookupLatest(rootAddr storage.Address) *LookupParams
- func LookupLatestVersionInPeriod(rootAddr storage.Address, period uint32) *LookupParams
- func LookupVersion(rootAddr storage.Address, period, version uint32) *LookupParams
- func NewLookupParams(rootAddr storage.Address, period, version uint32, limit uint32) *LookupParams
- type Request
- func (r *Request) Frequency() uint64
- func (r *Request) IsNew() bool
- func (r *Request) IsUpdate() bool
- func (r *Request) MarshalJSON() (rawData []byte, err error)
- func (r *Request) Multihash() bool
- func (r *Request) Name() string
- func (r *Request) Owner() common.Address
- func (r *Request) Period() uint32
- func (r *Request) RootAddr() storage.Address
- func (r *Request) SetData(data []byte, multihash bool)
- func (r *Request) Sign(signer Signer) error
- func (r *Request) StartTime() Timestamp
- func (r *Request) UnmarshalJSON(rawData []byte) error
- func (r *Request) Version() uint32
- type ResourceMetadata
- type Signature
- type SignedResourceUpdate
- type Signer
- type TestHandler
- type Timestamp
- type UpdateLookup
Constants ¶
const ( ErrInit = iota ErrNotFound ErrIO ErrInvalidValue ErrDataOverflow ErrNothingToReturn ErrCorruptData ErrInvalidSignature ErrNotSynced ErrPeriodDepth ErrCnt )
Variables ¶
var TimestampProvider timestampProvider = NewDefaultTimestampProvider()
TimestampProvider sets the time source of the mru package
Functions ¶
Types ¶
type DefaultTimestampProvider ¶
type DefaultTimestampProvider struct { }
func NewDefaultTimestampProvider ¶
func NewDefaultTimestampProvider() *DefaultTimestampProvider
NewDefaultTimestampProvider creates a system clock based timestamp provider
func (*DefaultTimestampProvider) Now ¶
func (dtp *DefaultTimestampProvider) Now() Timestamp
Now returns the current time according to this provider
type Error ¶
type Error struct {
// contains filtered or unexported fields
}
Error is a the typed error object used for Mutable Resources
type GenericSigner ¶
type GenericSigner struct { PrivKey *ecdsa.PrivateKey // contains filtered or unexported fields }
GenericSigner implements the Signer interface It is the vanilla signer that probably should be used in most cases
func NewGenericSigner ¶
func NewGenericSigner(privKey *ecdsa.PrivateKey) *GenericSigner
NewGenericSigner builds a signer that will sign everything with the provided private key
func (*GenericSigner) Address ¶
func (s *GenericSigner) Address() common.Address
PublicKey returns the public key of the signer's private key
type Handler ¶
type Handler struct { HashSize int // contains filtered or unexported fields }
func NewHandler ¶
func NewHandler(params *HandlerParams) (*Handler, error)
NewHandler creates a new Mutable Resource API
func (*Handler) GetContent ¶
GetContent retrieves the data payload of the last synced update of the Mutable Resource
func (*Handler) GetLastPeriod ¶
GetLastPeriod retrieves the period of the last synced update of the Mutable Resource
func (*Handler) GetVersion ¶
GetVersion retrieves the period of the last synced update of the Mutable Resource
func (*Handler) Load ¶
Load retrieves the Mutable Resource metadata chunk stored at rootAddr Upon retrieval it creates/updates the index entry for it with metadata corresponding to the chunk contents
func (*Handler) Lookup ¶
func (h *Handler) Lookup(ctx context.Context, params *LookupParams) (*resource, error)
Lookup retrieves a specific or latest version of the resource update with metadata chunk at params.Root Lookup works differently depending on the configuration of `LookupParams` See the `LookupParams` documentation and helper functions: `LookupLatest`, `LookupLatestVersionInPeriod` and `LookupVersion` When looking for the latest update, it starts at the next period after the current time. upon failure tries the corresponding keys of each previous period until one is found (or startTime is reached, in which case there are no updates).
func (*Handler) LookupPrevious ¶
func (h *Handler) LookupPrevious(ctx context.Context, params *LookupParams) (*resource, error)
LookupPrevious returns the resource before the one currently loaded in the resource cache This is useful where resource updates are used incrementally in contrast to merely replacing content. Requires a cached resource object to determine the current state of the resource.
func (*Handler) NewUpdateRequest ¶
func (h *Handler) NewUpdateRequest(ctx context.Context, rootAddr storage.Address) (updateRequest *Request, err error)
NewUpdateRequest prepares an UpdateRequest structure with all the necessary information to just add the desired data and sign it. The resulting structure can then be signed and passed to Handler.Update to be verified and sent
func (*Handler) Update ¶
Update adds an actual data update Uses the Mutable Resource metadata currently loaded in the resources map entry. It is the caller's responsibility to make sure that this data is not stale. Note that a Mutable Resource update cannot span chunks, and thus has a MAX NET LENGTH 4096, INCLUDING update header data and signature. 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 on the network.
type HandlerParams ¶
type HandlerParams struct {
QueryMaxPeriods uint32
}
HandlerParams pass parameters to the Handler constructor NewHandler Signer and TimestampProvider are mandatory parameters
type LookupParams ¶
type LookupParams struct { UpdateLookup Limit uint32 }
LookupParams is used to specify constraints when performing an update lookup Limit defines whether or not the lookup should be limited If Limit is set to true then Max defines the amount of hops that can be performed
func LookupLatest ¶
func LookupLatest(rootAddr storage.Address) *LookupParams
LookupLatest generates lookup parameters that look for the latest version of a resource
func LookupLatestVersionInPeriod ¶
func LookupLatestVersionInPeriod(rootAddr storage.Address, period uint32) *LookupParams
LookupLatestVersionInPeriod generates lookup parameters that look for the latest version of a resource in a given period
func LookupVersion ¶
func LookupVersion(rootAddr storage.Address, period, version uint32) *LookupParams
LookupVersion generates lookup parameters that look for a specific version of a resource
func NewLookupParams ¶
func NewLookupParams(rootAddr storage.Address, period, version uint32, limit uint32) *LookupParams
func (*LookupParams) RootAddr ¶
func (r *LookupParams) RootAddr() storage.Address
RootAddr returns the metadata chunk address
type Request ¶
type Request struct { SignedResourceUpdate // contains filtered or unexported fields }
Request represents an update and/or resource create message
func NewCreateRequest ¶
func NewCreateRequest(metadata *ResourceMetadata) (request *Request, err error)
NewCreateRequest returns a request to create a new resource
func NewCreateUpdateRequest ¶
func NewCreateUpdateRequest(metadata *ResourceMetadata) (*Request, error)
NewCreateUpdateRequest returns a ready to sign request to create and initialize a resource with data
func (*Request) MarshalJSON ¶
MarshalJSON takes an update request and encodes it as a JSON structure into a byte array Implements json.Marshaler interface
func (*Request) Multihash ¶
Multihash returns true if the resource data should be interpreted as a multihash
func (*Request) Sign ¶
Sign executes the signature to validate the resource and sets the owner address field
func (*Request) UnmarshalJSON ¶
UnmarshalJSON takes a JSON structure stored in a byte array and populates the Request object Implements json.Unmarshaler interface
type ResourceMetadata ¶
type ResourceMetadata struct { StartTime Timestamp // time at which the resource starts to be valid Frequency uint64 // expected update frequency for the resource Name string // name of the resource, for the reference of the user or to disambiguate resources with same starttime, frequency, owneraddr Owner common.Address // public address of the resource owner }
ResourceMetadata encapsulates the immutable information about a mutable resource :) once serialized into a chunk, the resource can be retrieved by knowing its content-addressed rootAddr
type Signature ¶
type Signature [signatureLength]byte
Signature is an alias for a static byte array with the size of a signature
type SignedResourceUpdate ¶
type SignedResourceUpdate struct {
// contains filtered or unexported fields
}
SignedResourceUpdate represents a resource update with all the necessary information to prove ownership of the resource
func (*SignedResourceUpdate) GetDigest ¶
func (r *SignedResourceUpdate) GetDigest() (result common.Hash, err error)
GetDigest creates the resource update digest used in signatures (formerly known as keyDataHash) the serialized payload is cached in .binaryData
func (*SignedResourceUpdate) Multihash ¶
func (r *SignedResourceUpdate) Multihash() bool
Multihash specifies whether the resource data should be interpreted as multihash
func (*SignedResourceUpdate) Sign ¶
func (r *SignedResourceUpdate) Sign(signer Signer) error
Sign executes the signature to validate the resource
func (*SignedResourceUpdate) Verify ¶
func (r *SignedResourceUpdate) Verify() (err error)
Verify checks that signatures are valid and that the signer owns the resource to be updated
type TestHandler ¶
type TestHandler struct {
*Handler
}
func NewTestHandler ¶
func NewTestHandler(datadir string, params *HandlerParams) (*TestHandler, error)
NewTestHandler creates Handler object to be used for testing purposes.
func (*TestHandler) Close ¶
func (t *TestHandler) Close()
type Timestamp ¶
type Timestamp struct {
Time uint64 // Unix epoch timestamp, in seconds
}
Encodes a point in time as a Unix epoch
type UpdateLookup ¶
type UpdateLookup struct {
// contains filtered or unexported fields
}
UpdateLookup represents the components of a resource update search key
func (*UpdateLookup) UpdateAddr ¶
func (u *UpdateLookup) UpdateAddr() (updateAddr storage.Address)
UpdateAddr calculates the resource update chunk address corresponding to this lookup key