github.com/Blockdaemon/celo-blockchain@v0.0.0-20200129231733-e667f6b08419/swarm/storage/feed/id.go (about)

     1  // Copyright 2018 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package feed
    18  
    19  import (
    20  	"fmt"
    21  	"hash"
    22  	"strconv"
    23  
    24  	"github.com/ethereum/go-ethereum/common"
    25  	"github.com/ethereum/go-ethereum/swarm/storage"
    26  	"github.com/ethereum/go-ethereum/swarm/storage/feed/lookup"
    27  )
    28  
    29  // ID uniquely identifies an update on the network.
    30  type ID struct {
    31  	Feed         `json:"feed"`
    32  	lookup.Epoch `json:"epoch"`
    33  }
    34  
    35  // ID layout:
    36  // Feed feedLength bytes
    37  // Epoch EpochLength
    38  const idLength = feedLength + lookup.EpochLength
    39  
    40  // Addr calculates the feed update chunk address corresponding to this ID
    41  func (u *ID) Addr() (updateAddr storage.Address) {
    42  	serializedData := make([]byte, idLength)
    43  	var cursor int
    44  	u.Feed.binaryPut(serializedData[cursor : cursor+feedLength])
    45  	cursor += feedLength
    46  
    47  	eid := u.Epoch.ID()
    48  	copy(serializedData[cursor:cursor+lookup.EpochLength], eid[:])
    49  
    50  	hasher := hashPool.Get().(hash.Hash)
    51  	defer hashPool.Put(hasher)
    52  	hasher.Reset()
    53  	hasher.Write(serializedData)
    54  	return hasher.Sum(nil)
    55  }
    56  
    57  // binaryPut serializes this instance into the provided slice
    58  func (u *ID) binaryPut(serializedData []byte) error {
    59  	if len(serializedData) != idLength {
    60  		return NewErrorf(ErrInvalidValue, "Incorrect slice size to serialize ID. Expected %d, got %d", idLength, len(serializedData))
    61  	}
    62  	var cursor int
    63  	if err := u.Feed.binaryPut(serializedData[cursor : cursor+feedLength]); err != nil {
    64  		return err
    65  	}
    66  	cursor += feedLength
    67  
    68  	epochBytes, err := u.Epoch.MarshalBinary()
    69  	if err != nil {
    70  		return err
    71  	}
    72  	copy(serializedData[cursor:cursor+lookup.EpochLength], epochBytes[:])
    73  	cursor += lookup.EpochLength
    74  
    75  	return nil
    76  }
    77  
    78  // binaryLength returns the expected size of this structure when serialized
    79  func (u *ID) binaryLength() int {
    80  	return idLength
    81  }
    82  
    83  // binaryGet restores the current instance from the information contained in the passed slice
    84  func (u *ID) binaryGet(serializedData []byte) error {
    85  	if len(serializedData) != idLength {
    86  		return NewErrorf(ErrInvalidValue, "Incorrect slice size to read ID. Expected %d, got %d", idLength, len(serializedData))
    87  	}
    88  
    89  	var cursor int
    90  	if err := u.Feed.binaryGet(serializedData[cursor : cursor+feedLength]); err != nil {
    91  		return err
    92  	}
    93  	cursor += feedLength
    94  
    95  	if err := u.Epoch.UnmarshalBinary(serializedData[cursor : cursor+lookup.EpochLength]); err != nil {
    96  		return err
    97  	}
    98  	cursor += lookup.EpochLength
    99  
   100  	return nil
   101  }
   102  
   103  // FromValues deserializes this instance from a string key-value store
   104  // useful to parse query strings
   105  func (u *ID) FromValues(values Values) error {
   106  	level, _ := strconv.ParseUint(values.Get("level"), 10, 32)
   107  	u.Epoch.Level = uint8(level)
   108  	u.Epoch.Time, _ = strconv.ParseUint(values.Get("time"), 10, 64)
   109  
   110  	if u.Feed.User == (common.Address{}) {
   111  		return u.Feed.FromValues(values)
   112  	}
   113  	return nil
   114  }
   115  
   116  // AppendValues serializes this structure into the provided string key-value store
   117  // useful to build query strings
   118  func (u *ID) AppendValues(values Values) {
   119  	values.Set("level", fmt.Sprintf("%d", u.Epoch.Level))
   120  	values.Set("time", fmt.Sprintf("%d", u.Epoch.Time))
   121  	u.Feed.AppendValues(values)
   122  }