github.com/xxRanger/go-ethereum@v1.8.23/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/feed/lookup"
    26  
    27  	"github.com/ethereum/go-ethereum/swarm/storage"
    28  )
    29  
    30  // ID uniquely identifies an update on the network.
    31  type ID struct {
    32  	Feed         `json:"feed"`
    33  	lookup.Epoch `json:"epoch"`
    34  }
    35  
    36  // ID layout:
    37  // Feed feedLength bytes
    38  // Epoch EpochLength
    39  const idLength = feedLength + lookup.EpochLength
    40  
    41  // Addr calculates the feed update chunk address corresponding to this ID
    42  func (u *ID) Addr() (updateAddr storage.Address) {
    43  	serializedData := make([]byte, idLength)
    44  	var cursor int
    45  	u.Feed.binaryPut(serializedData[cursor : cursor+feedLength])
    46  	cursor += feedLength
    47  
    48  	eid := u.Epoch.ID()
    49  	copy(serializedData[cursor:cursor+lookup.EpochLength], eid[:])
    50  
    51  	hasher := hashPool.Get().(hash.Hash)
    52  	defer hashPool.Put(hasher)
    53  	hasher.Reset()
    54  	hasher.Write(serializedData)
    55  	return hasher.Sum(nil)
    56  }
    57  
    58  // binaryPut serializes this instance into the provided slice
    59  func (u *ID) binaryPut(serializedData []byte) error {
    60  	if len(serializedData) != idLength {
    61  		return NewErrorf(ErrInvalidValue, "Incorrect slice size to serialize ID. Expected %d, got %d", idLength, len(serializedData))
    62  	}
    63  	var cursor int
    64  	if err := u.Feed.binaryPut(serializedData[cursor : cursor+feedLength]); err != nil {
    65  		return err
    66  	}
    67  	cursor += feedLength
    68  
    69  	epochBytes, err := u.Epoch.MarshalBinary()
    70  	if err != nil {
    71  		return err
    72  	}
    73  	copy(serializedData[cursor:cursor+lookup.EpochLength], epochBytes[:])
    74  	cursor += lookup.EpochLength
    75  
    76  	return nil
    77  }
    78  
    79  // binaryLength returns the expected size of this structure when serialized
    80  func (u *ID) binaryLength() int {
    81  	return idLength
    82  }
    83  
    84  // binaryGet restores the current instance from the information contained in the passed slice
    85  func (u *ID) binaryGet(serializedData []byte) error {
    86  	if len(serializedData) != idLength {
    87  		return NewErrorf(ErrInvalidValue, "Incorrect slice size to read ID. Expected %d, got %d", idLength, len(serializedData))
    88  	}
    89  
    90  	var cursor int
    91  	if err := u.Feed.binaryGet(serializedData[cursor : cursor+feedLength]); err != nil {
    92  		return err
    93  	}
    94  	cursor += feedLength
    95  
    96  	if err := u.Epoch.UnmarshalBinary(serializedData[cursor : cursor+lookup.EpochLength]); err != nil {
    97  		return err
    98  	}
    99  	cursor += lookup.EpochLength
   100  
   101  	return nil
   102  }
   103  
   104  // FromValues deserializes this instance from a string key-value store
   105  // useful to parse query strings
   106  func (u *ID) FromValues(values Values) error {
   107  	level, _ := strconv.ParseUint(values.Get("level"), 10, 32)
   108  	u.Epoch.Level = uint8(level)
   109  	u.Epoch.Time, _ = strconv.ParseUint(values.Get("time"), 10, 64)
   110  
   111  	if u.Feed.User == (common.Address{}) {
   112  		return u.Feed.FromValues(values)
   113  	}
   114  	return nil
   115  }
   116  
   117  // AppendValues serializes this structure into the provided string key-value store
   118  // useful to build query strings
   119  func (u *ID) AppendValues(values Values) {
   120  	values.Set("level", fmt.Sprintf("%d", u.Epoch.Level))
   121  	values.Set("time", fmt.Sprintf("%d", u.Epoch.Time))
   122  	u.Feed.AppendValues(values)
   123  }