From 2d212ed2466b9be72bf05ad14a49fe98fba10827 Mon Sep 17 00:00:00 2001 From: Javier Peletier Date: Sun, 16 Sep 2018 23:11:00 +0200 Subject: [PATCH] swarm/storage/mru: Add version / header for future use --- swarm/storage/mru/doc.go | 12 +++---- swarm/storage/mru/handler.go | 2 +- swarm/storage/mru/request.go | 14 +++++--- swarm/storage/mru/request_test.go | 6 ++-- swarm/storage/mru/update.go | 55 ++++++++++++++++++++++--------- swarm/storage/mru/update_test.go | 2 +- 6 files changed, 60 insertions(+), 31 deletions(-) diff --git a/swarm/storage/mru/doc.go b/swarm/storage/mru/doc.go index 724d019fc5..19330e0c1a 100644 --- a/swarm/storage/mru/doc.go +++ b/swarm/storage/mru/doc.go @@ -33,12 +33,12 @@ Structure Summary: Request: Resource update with signature ResourceUpdate: headers + data - UpdateHeader: (placeholder, to be deleted) - ID: Information about how to locate a specific update - View: Author of the update and what is updating - Topic: Item that the updates are about - User: User who updates the resource - Epoch: time slot where the update is stored + Header: Protocol version and reserved for future use placeholders + ID: Information about how to locate a specific update + View: Author of the update and what is updating + Topic: Item that the updates are about + User: User who updates the resource + Epoch: time slot where the update is stored */ package mru diff --git a/swarm/storage/mru/handler.go b/swarm/storage/mru/handler.go index aa297aa613..b615e1b077 100644 --- a/swarm/storage/mru/handler.go +++ b/swarm/storage/mru/handler.go @@ -123,13 +123,13 @@ func (h *Handler) GetContent(view *View) (storage.Address, []byte, error) { // 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 (h *Handler) NewRequest(ctx context.Context, view *View) (request *Request, err error) { - if view == nil { return nil, NewError(ErrInvalidValue, "view cannot be nil") } now := TimestampProvider.Now().Time request = new(Request) + request.Header.Version = ProtocolVersion query := NewQueryLatest(view, lookup.NoClue) diff --git a/swarm/storage/mru/request.go b/swarm/storage/mru/request.go index cbc02bedd3..3442c9f436 100644 --- a/swarm/storage/mru/request.go +++ b/swarm/storage/mru/request.go @@ -38,8 +38,9 @@ type Request struct { // updateRequestJSON represents a JSON-serialized UpdateRequest type updateRequestJSON struct { ID - Data string `json:"data,omitempty"` - Signature string `json:"signature,omitempty"` + ProtocolVersion uint8 `json:"protocolVersion"` + Data string `json:"data,omitempty"` + Signature string `json:"signature,omitempty"` } var zeroAddr = common.Address{} @@ -58,6 +59,7 @@ func NewFirstRequest(topic Topic) *Request { now := TimestampProvider.Now().Time request.Epoch = lookup.GetFirstEpoch(now) request.View.Topic = topic + request.Header.Version = ProtocolVersion return request } @@ -230,6 +232,7 @@ func (r *Request) AppendValues(values Values) []byte { func (r *Request) fromJSON(j *updateRequestJSON) error { r.ID = j.ID + r.Header.Version = j.ProtocolVersion var err error if j.Data != "" { @@ -273,9 +276,10 @@ func (r *Request) MarshalJSON() (rawData []byte, err error) { } requestJSON := &updateRequestJSON{ - ID: r.ID, - Data: dataString, - Signature: signatureString, + ID: r.ID, + ProtocolVersion: r.Header.Version, + Data: dataString, + Signature: signatureString, } return json.Marshal(requestJSON) diff --git a/swarm/storage/mru/request_test.go b/swarm/storage/mru/request_test.go index 0886f008fb..87eef99a0f 100644 --- a/swarm/storage/mru/request_test.go +++ b/swarm/storage/mru/request_test.go @@ -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 // proof of ownership - const expectedSignature = "0x1cbdad7702b7d43ca983dc9f2ed87e73984288cdae6a8844e44688ee22c72080516fcd65a894b894b7b41ac780d5ce5d9fb527dc7126ea876501948d2bb6880d00" - const expectedJSON = `{"view":{"topic":"0x6120676f6f64207265736f75726365206e616d65000000000000000000000000","user":"0x876a8936a7cd0b79ef0735ad0896c1afe278781c"},"epoch":{"level":1,"time":1000},"data":"0x5468697320686f75722773207570646174653a20537761726d2039392e3020686173206265656e2072656c656173656421"}` + const expectedSignature = "0x32c2d2c7224e24e4d3ae6a10595fc6e945f1b3ecdf548a04d8247c240a50c9240076aa7730abad6c8a46dfea00cfb8f43b6211f02db5c4cc5ed8584cb0212a4d00" + 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. 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) } - compareByteSliceToExpectedHex(t, "chunk", chunk.Data(), "0x776f726c64206e657773207265706f72742c20657665727920686f7572000000876a8936a7cd0b79ef0735ad0896c1afe278781ce803000000000019416c206269656e206861636572206a616dc3a173206c652066616c7461207072656d696f376972cfb8bba6ad0c0f15e17f28bf03b6829649fddfc6b66d9de79a67f85c990982b513b09e8fd5365bde6920c8c73582ebf6f7fc85938b6d0dd285a3f18e2201") + compareByteSliceToExpectedHex(t, "chunk", chunk.Data(), "0x0000000000000000776f726c64206e657773207265706f72742c20657665727920686f7572000000876a8936a7cd0b79ef0735ad0896c1afe278781ce803000000000019416c206269656e206861636572206a616dc3a173206c652066616c7461207072656d696f5a0ffe0bc27f207cd5b00944c8b9cee93e08b89b5ada777f123ac535189333f174a6a4ca2f43a92c4a477a49d774813c36ce8288552c58e6205b0ac35d0507eb00") var recovered Request recovered.fromChunk(chunk.Address(), chunk.Data()) diff --git a/swarm/storage/mru/update.go b/swarm/storage/mru/update.go index 05d5e04f00..6aa57fce1c 100644 --- a/swarm/storage/mru/update.go +++ b/swarm/storage/mru/update.go @@ -17,22 +17,32 @@ package mru import ( + "fmt" + "strconv" + "github.com/ethereum/go-ethereum/swarm/chunk" ) -// ResourceUpdate encapsulates the information sent as part of a resource update -type ResourceUpdate struct { - ID // metainformation about this resource update - data []byte // actual data payload +// ProtocolVersion defines the current version of the protocol that will be included in each update message +const ProtocolVersion uint8 = 0 + +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) -// Data: -// data (datalength bytes) -// -// Minimum size is Header + 1 (minimum data length, enforced) -const minimumUpdateDataLength = idLength + 1 -const maxUpdateDataLength = chunk.DefaultSize - signatureLength - idLength +// ResourceUpdate encapsulates the information sent as part of a resource update +type ResourceUpdate struct { + Header Header // + ID // Resource update identifying information + data []byte // actual data payload +} + +const minimumUpdateDataLength = idLength + headerLength + 1 +const maxUpdateDataLength = chunk.DefaultSize - signatureLength - idLength - headerLength // binaryPut serializes the resource update information into the given slice func (r *ResourceUpdate) binaryPut(serializedData []byte) error { @@ -50,7 +60,12 @@ func (r *ResourceUpdate) binaryPut(serializedData []byte) error { } 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 { 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 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 @@ -73,9 +88,16 @@ func (r *ResourceUpdate) binaryGet(serializedData []byte) error { if len(serializedData) < minimumUpdateDataLength { return NewErrorf(ErrNothingToReturn, "chunk less than %d bytes cannot be a resource update chunk", minimumUpdateDataLength) } - dataLength := len(serializedData) - idLength - var cursor int + dataLength := len(serializedData) - idLength - headerLength // 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 { return err } @@ -96,6 +118,8 @@ func (r *ResourceUpdate) binaryGet(serializedData []byte) error { // useful to parse query strings func (r *ResourceUpdate) FromValues(values Values, data []byte) error { r.data = data + version, _ := strconv.ParseUint(values.Get("protocolVersion"), 10, 32) + r.Header.Version = uint8(version) return r.ID.FromValues(values) } @@ -103,5 +127,6 @@ func (r *ResourceUpdate) FromValues(values Values, data []byte) error { // useful to build query strings func (r *ResourceUpdate) AppendValues(values Values) []byte { r.ID.AppendValues(values) + values.Set("protocolVersion", fmt.Sprintf("%d", r.Header.Version)) return r.data } diff --git a/swarm/storage/mru/update_test.go b/swarm/storage/mru/update_test.go index fdaec82af4..bd706d83ae 100644 --- a/swarm/storage/mru/update_test.go +++ b/swarm/storage/mru/update_test.go @@ -28,7 +28,7 @@ func getTestResourceUpdate() *ResourceUpdate { } func TestResourceUpdateSerializer(t *testing.T) { - testBinarySerializerRecovery(t, getTestResourceUpdate(), "0x776f726c64206e657773207265706f72742c20657665727920686f7572000000876a8936a7cd0b79ef0735ad0896c1afe278781ce803000000000019456c20717565206c6565206d7563686f207920616e6461206d7563686f2c207665206d7563686f20792073616265206d7563686f") + testBinarySerializerRecovery(t, getTestResourceUpdate(), "0x0000000000000000776f726c64206e657773207265706f72742c20657665727920686f7572000000876a8936a7cd0b79ef0735ad0896c1afe278781ce803000000000019456c20717565206c6565206d7563686f207920616e6461206d7563686f2c207665206d7563686f20792073616265206d7563686f") } func TestResourceUpdateLengthCheck(t *testing.T) {