mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 10:22:23 +00:00
swarm/storage/mru: Add version / header for future use
This commit is contained in:
parent
c3897268cc
commit
2d212ed246
6 changed files with 60 additions and 31 deletions
|
|
@ -33,12 +33,12 @@ Structure Summary:
|
||||||
|
|
||||||
Request: Resource update with signature
|
Request: Resource update with signature
|
||||||
ResourceUpdate: headers + data
|
ResourceUpdate: headers + data
|
||||||
UpdateHeader: (placeholder, to be deleted)
|
Header: Protocol version and reserved for future use placeholders
|
||||||
ID: Information about how to locate a specific update
|
ID: Information about how to locate a specific update
|
||||||
View: Author of the update and what is updating
|
View: Author of the update and what is updating
|
||||||
Topic: Item that the updates are about
|
Topic: Item that the updates are about
|
||||||
User: User who updates the resource
|
User: User who updates the resource
|
||||||
Epoch: time slot where the update is stored
|
Epoch: time slot where the update is stored
|
||||||
|
|
||||||
*/
|
*/
|
||||||
package mru
|
package mru
|
||||||
|
|
|
||||||
|
|
@ -123,13 +123,13 @@ func (h *Handler) GetContent(view *View) (storage.Address, []byte, error) {
|
||||||
// just add the desired data and sign it.
|
// 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
|
// The resulting structure can then be signed and passed to Handler.Update to be verified and sent
|
||||||
func (h *Handler) NewRequest(ctx context.Context, view *View) (request *Request, err error) {
|
func (h *Handler) NewRequest(ctx context.Context, view *View) (request *Request, err error) {
|
||||||
|
|
||||||
if view == nil {
|
if view == nil {
|
||||||
return nil, NewError(ErrInvalidValue, "view cannot be nil")
|
return nil, NewError(ErrInvalidValue, "view cannot be nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
now := TimestampProvider.Now().Time
|
now := TimestampProvider.Now().Time
|
||||||
request = new(Request)
|
request = new(Request)
|
||||||
|
request.Header.Version = ProtocolVersion
|
||||||
|
|
||||||
query := NewQueryLatest(view, lookup.NoClue)
|
query := NewQueryLatest(view, lookup.NoClue)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,8 +38,9 @@ type Request struct {
|
||||||
// updateRequestJSON represents a JSON-serialized UpdateRequest
|
// updateRequestJSON represents a JSON-serialized UpdateRequest
|
||||||
type updateRequestJSON struct {
|
type updateRequestJSON struct {
|
||||||
ID
|
ID
|
||||||
Data string `json:"data,omitempty"`
|
ProtocolVersion uint8 `json:"protocolVersion"`
|
||||||
Signature string `json:"signature,omitempty"`
|
Data string `json:"data,omitempty"`
|
||||||
|
Signature string `json:"signature,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var zeroAddr = common.Address{}
|
var zeroAddr = common.Address{}
|
||||||
|
|
@ -58,6 +59,7 @@ func NewFirstRequest(topic Topic) *Request {
|
||||||
now := TimestampProvider.Now().Time
|
now := TimestampProvider.Now().Time
|
||||||
request.Epoch = lookup.GetFirstEpoch(now)
|
request.Epoch = lookup.GetFirstEpoch(now)
|
||||||
request.View.Topic = topic
|
request.View.Topic = topic
|
||||||
|
request.Header.Version = ProtocolVersion
|
||||||
|
|
||||||
return request
|
return request
|
||||||
}
|
}
|
||||||
|
|
@ -230,6 +232,7 @@ func (r *Request) AppendValues(values Values) []byte {
|
||||||
func (r *Request) fromJSON(j *updateRequestJSON) error {
|
func (r *Request) fromJSON(j *updateRequestJSON) error {
|
||||||
|
|
||||||
r.ID = j.ID
|
r.ID = j.ID
|
||||||
|
r.Header.Version = j.ProtocolVersion
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
if j.Data != "" {
|
if j.Data != "" {
|
||||||
|
|
@ -273,9 +276,10 @@ func (r *Request) MarshalJSON() (rawData []byte, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
requestJSON := &updateRequestJSON{
|
requestJSON := &updateRequestJSON{
|
||||||
ID: r.ID,
|
ID: r.ID,
|
||||||
Data: dataString,
|
ProtocolVersion: r.Header.Version,
|
||||||
Signature: signatureString,
|
Data: dataString,
|
||||||
|
Signature: signatureString,
|
||||||
}
|
}
|
||||||
|
|
||||||
return json.Marshal(requestJSON)
|
return json.Marshal(requestJSON)
|
||||||
|
|
|
||||||
|
|
@ -79,8 +79,8 @@ func TestEncodingDecodingUpdateRequests(t *testing.T) {
|
||||||
// and recover the information above. To sign an update, we need the rootAddr and the metaHash to construct
|
// and recover the information above. To sign an update, we need the rootAddr and the metaHash to construct
|
||||||
// proof of ownership
|
// proof of ownership
|
||||||
|
|
||||||
const expectedSignature = "0x1cbdad7702b7d43ca983dc9f2ed87e73984288cdae6a8844e44688ee22c72080516fcd65a894b894b7b41ac780d5ce5d9fb527dc7126ea876501948d2bb6880d00"
|
const expectedSignature = "0x32c2d2c7224e24e4d3ae6a10595fc6e945f1b3ecdf548a04d8247c240a50c9240076aa7730abad6c8a46dfea00cfb8f43b6211f02db5c4cc5ed8584cb0212a4d00"
|
||||||
const expectedJSON = `{"view":{"topic":"0x6120676f6f64207265736f75726365206e616d65000000000000000000000000","user":"0x876a8936a7cd0b79ef0735ad0896c1afe278781c"},"epoch":{"level":1,"time":1000},"data":"0x5468697320686f75722773207570646174653a20537761726d2039392e3020686173206265656e2072656c656173656421"}`
|
const expectedJSON = `{"view":{"topic":"0x6120676f6f64207265736f75726365206e616d65000000000000000000000000","user":"0x876a8936a7cd0b79ef0735ad0896c1afe278781c"},"epoch":{"time":1000,"level":1},"protocolVersion":0,"data":"0x5468697320686f75722773207570646174653a20537761726d2039392e3020686173206265656e2072656c656173656421"}`
|
||||||
|
|
||||||
//Put together an unsigned update request that we will serialize to send it to the signer.
|
//Put together an unsigned update request that we will serialize to send it to the signer.
|
||||||
data := []byte("This hour's update: Swarm 99.0 has been released!")
|
data := []byte("This hour's update: Swarm 99.0 has been released!")
|
||||||
|
|
@ -225,7 +225,7 @@ func TestUpdateChunkSerializationErrorChecking(t *testing.T) {
|
||||||
t.Fatalf("error creating update chunk:%s", err)
|
t.Fatalf("error creating update chunk:%s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
compareByteSliceToExpectedHex(t, "chunk", chunk.Data(), "0x776f726c64206e657773207265706f72742c20657665727920686f7572000000876a8936a7cd0b79ef0735ad0896c1afe278781ce803000000000019416c206269656e206861636572206a616dc3a173206c652066616c7461207072656d696f376972cfb8bba6ad0c0f15e17f28bf03b6829649fddfc6b66d9de79a67f85c990982b513b09e8fd5365bde6920c8c73582ebf6f7fc85938b6d0dd285a3f18e2201")
|
compareByteSliceToExpectedHex(t, "chunk", chunk.Data(), "0x0000000000000000776f726c64206e657773207265706f72742c20657665727920686f7572000000876a8936a7cd0b79ef0735ad0896c1afe278781ce803000000000019416c206269656e206861636572206a616dc3a173206c652066616c7461207072656d696f5a0ffe0bc27f207cd5b00944c8b9cee93e08b89b5ada777f123ac535189333f174a6a4ca2f43a92c4a477a49d774813c36ce8288552c58e6205b0ac35d0507eb00")
|
||||||
|
|
||||||
var recovered Request
|
var recovered Request
|
||||||
recovered.fromChunk(chunk.Address(), chunk.Data())
|
recovered.fromChunk(chunk.Address(), chunk.Data())
|
||||||
|
|
|
||||||
|
|
@ -17,22 +17,32 @@
|
||||||
package mru
|
package mru
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/swarm/chunk"
|
"github.com/ethereum/go-ethereum/swarm/chunk"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ResourceUpdate encapsulates the information sent as part of a resource update
|
// ProtocolVersion defines the current version of the protocol that will be included in each update message
|
||||||
type ResourceUpdate struct {
|
const ProtocolVersion uint8 = 0
|
||||||
ID // metainformation about this resource update
|
|
||||||
data []byte // actual data payload
|
const headerLength = 8
|
||||||
|
|
||||||
|
// Header defines a update message header including a protocol version byte
|
||||||
|
type Header struct {
|
||||||
|
Version uint8 // Protocol version
|
||||||
|
Padding [headerLength - 1]uint8 // reserved for future use
|
||||||
}
|
}
|
||||||
|
|
||||||
// Header: (see updateHeader)
|
// ResourceUpdate encapsulates the information sent as part of a resource update
|
||||||
// Data:
|
type ResourceUpdate struct {
|
||||||
// data (datalength bytes)
|
Header Header //
|
||||||
//
|
ID // Resource update identifying information
|
||||||
// Minimum size is Header + 1 (minimum data length, enforced)
|
data []byte // actual data payload
|
||||||
const minimumUpdateDataLength = idLength + 1
|
}
|
||||||
const maxUpdateDataLength = chunk.DefaultSize - signatureLength - idLength
|
|
||||||
|
const minimumUpdateDataLength = idLength + headerLength + 1
|
||||||
|
const maxUpdateDataLength = chunk.DefaultSize - signatureLength - idLength - headerLength
|
||||||
|
|
||||||
// binaryPut serializes the resource update information into the given slice
|
// binaryPut serializes the resource update information into the given slice
|
||||||
func (r *ResourceUpdate) binaryPut(serializedData []byte) error {
|
func (r *ResourceUpdate) binaryPut(serializedData []byte) error {
|
||||||
|
|
@ -50,7 +60,12 @@ func (r *ResourceUpdate) binaryPut(serializedData []byte) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
var cursor int
|
var cursor int
|
||||||
// serialize header (see updateHeader)
|
// serialize Header
|
||||||
|
serializedData[cursor] = r.Header.Version
|
||||||
|
copy(serializedData[cursor+1:headerLength], r.Header.Padding[:headerLength-1])
|
||||||
|
cursor += headerLength
|
||||||
|
|
||||||
|
// serialize ID
|
||||||
if err := r.ID.binaryPut(serializedData[cursor : cursor+idLength]); err != nil {
|
if err := r.ID.binaryPut(serializedData[cursor : cursor+idLength]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -65,7 +80,7 @@ func (r *ResourceUpdate) binaryPut(serializedData []byte) error {
|
||||||
|
|
||||||
// binaryLength returns the expected number of bytes this structure will take to encode
|
// binaryLength returns the expected number of bytes this structure will take to encode
|
||||||
func (r *ResourceUpdate) binaryLength() int {
|
func (r *ResourceUpdate) binaryLength() int {
|
||||||
return idLength + len(r.data)
|
return idLength + headerLength + len(r.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// binaryGet populates this instance from the information contained in the passed byte slice
|
// binaryGet populates this instance from the information contained in the passed byte slice
|
||||||
|
|
@ -73,9 +88,16 @@ func (r *ResourceUpdate) binaryGet(serializedData []byte) error {
|
||||||
if len(serializedData) < minimumUpdateDataLength {
|
if len(serializedData) < minimumUpdateDataLength {
|
||||||
return NewErrorf(ErrNothingToReturn, "chunk less than %d bytes cannot be a resource update chunk", minimumUpdateDataLength)
|
return NewErrorf(ErrNothingToReturn, "chunk less than %d bytes cannot be a resource update chunk", minimumUpdateDataLength)
|
||||||
}
|
}
|
||||||
dataLength := len(serializedData) - idLength
|
dataLength := len(serializedData) - idLength - headerLength
|
||||||
var cursor int
|
|
||||||
// at this point we can be satisfied that we have the correct data length to read
|
// at this point we can be satisfied that we have the correct data length to read
|
||||||
|
|
||||||
|
var cursor int
|
||||||
|
|
||||||
|
// deserialize Header
|
||||||
|
r.Header.Version = serializedData[cursor] // extract the protocol version
|
||||||
|
copy(r.Header.Padding[:headerLength-1], serializedData[cursor+1:headerLength]) // extract the padding
|
||||||
|
cursor += headerLength
|
||||||
|
|
||||||
if err := r.ID.binaryGet(serializedData[cursor : cursor+idLength]); err != nil {
|
if err := r.ID.binaryGet(serializedData[cursor : cursor+idLength]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -96,6 +118,8 @@ func (r *ResourceUpdate) binaryGet(serializedData []byte) error {
|
||||||
// useful to parse query strings
|
// useful to parse query strings
|
||||||
func (r *ResourceUpdate) FromValues(values Values, data []byte) error {
|
func (r *ResourceUpdate) FromValues(values Values, data []byte) error {
|
||||||
r.data = data
|
r.data = data
|
||||||
|
version, _ := strconv.ParseUint(values.Get("protocolVersion"), 10, 32)
|
||||||
|
r.Header.Version = uint8(version)
|
||||||
return r.ID.FromValues(values)
|
return r.ID.FromValues(values)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -103,5 +127,6 @@ func (r *ResourceUpdate) FromValues(values Values, data []byte) error {
|
||||||
// useful to build query strings
|
// useful to build query strings
|
||||||
func (r *ResourceUpdate) AppendValues(values Values) []byte {
|
func (r *ResourceUpdate) AppendValues(values Values) []byte {
|
||||||
r.ID.AppendValues(values)
|
r.ID.AppendValues(values)
|
||||||
|
values.Set("protocolVersion", fmt.Sprintf("%d", r.Header.Version))
|
||||||
return r.data
|
return r.data
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ func getTestResourceUpdate() *ResourceUpdate {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestResourceUpdateSerializer(t *testing.T) {
|
func TestResourceUpdateSerializer(t *testing.T) {
|
||||||
testBinarySerializerRecovery(t, getTestResourceUpdate(), "0x776f726c64206e657773207265706f72742c20657665727920686f7572000000876a8936a7cd0b79ef0735ad0896c1afe278781ce803000000000019456c20717565206c6565206d7563686f207920616e6461206d7563686f2c207665206d7563686f20792073616265206d7563686f")
|
testBinarySerializerRecovery(t, getTestResourceUpdate(), "0x0000000000000000776f726c64206e657773207265706f72742c20657665727920686f7572000000876a8936a7cd0b79ef0735ad0896c1afe278781ce803000000000019456c20717565206c6565206d7563686f207920616e6461206d7563686f2c207665206d7563686f20792073616265206d7563686f")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestResourceUpdateLengthCheck(t *testing.T) {
|
func TestResourceUpdateLengthCheck(t *testing.T) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue