github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/swarm/storage/mru/metadata.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 12:09:50</date>
    10  //</624342683220971520>
    11  
    12  //
    13  //
    14  //
    15  //
    16  //
    17  //
    18  //
    19  //
    20  //
    21  //
    22  //
    23  //
    24  //
    25  //
    26  //
    27  
    28  package mru
    29  
    30  import (
    31  	"encoding/binary"
    32  	"hash"
    33  
    34  	"github.com/ethereum/go-ethereum/common"
    35  	"github.com/ethereum/go-ethereum/swarm/storage"
    36  )
    37  
    38  //
    39  //
    40  type ResourceMetadata struct {
    41  StartTime Timestamp      //
    42  Frequency uint64         //
    43  Name      string         //
    44  Owner     common.Address //
    45  }
    46  
    47  const frequencyLength = 8 //
    48  const nameLengthLength = 1
    49  
    50  //
    51  //
    52  //
    53  //
    54  //
    55  //
    56  //
    57  const minimumMetadataLength = chunkPrefixLength + timestampLength + frequencyLength + nameLengthLength + common.AddressLength
    58  
    59  //
    60  func (r *ResourceMetadata) binaryGet(serializedData []byte) error {
    61  	if len(serializedData) < minimumMetadataLength {
    62  		return NewErrorf(ErrInvalidValue, "Metadata chunk to deserialize is too short. Expected at least %d. Got %d.", minimumMetadataLength, len(serializedData))
    63  	}
    64  
    65  //
    66  	if serializedData[0] != 0 || serializedData[1] != 0 {
    67  		return NewError(ErrCorruptData, "Invalid metadata chunk")
    68  	}
    69  
    70  	cursor := 2
    71  metadataLength := int(binary.LittleEndian.Uint16(serializedData[cursor : cursor+2])) //
    72  	if metadataLength+chunkPrefixLength != len(serializedData) {
    73  		return NewErrorf(ErrCorruptData, "Incorrect declared metadata length. Expected %d, got %d.", metadataLength+chunkPrefixLength, len(serializedData))
    74  	}
    75  
    76  	cursor += 2
    77  
    78  	if err := r.StartTime.binaryGet(serializedData[cursor : cursor+timestampLength]); err != nil {
    79  		return err
    80  	}
    81  	cursor += timestampLength
    82  
    83  	r.Frequency = binary.LittleEndian.Uint64(serializedData[cursor : cursor+frequencyLength])
    84  	cursor += frequencyLength
    85  
    86  	nameLength := int(serializedData[cursor])
    87  	if nameLength+minimumMetadataLength > len(serializedData) {
    88  		return NewErrorf(ErrInvalidValue, "Metadata chunk to deserialize is too short when decoding resource name. Expected at least %d. Got %d.", nameLength+minimumMetadataLength, len(serializedData))
    89  	}
    90  	cursor++
    91  	r.Name = string(serializedData[cursor : cursor+nameLength])
    92  	cursor += nameLength
    93  
    94  	copy(r.Owner[:], serializedData[cursor:])
    95  	cursor += common.AddressLength
    96  	if cursor != len(serializedData) {
    97  		return NewErrorf(ErrInvalidValue, "Metadata chunk has leftover data after deserialization. %d left to read", len(serializedData)-cursor)
    98  	}
    99  	return nil
   100  }
   101  
   102  //
   103  func (r *ResourceMetadata) binaryPut(serializedData []byte) error {
   104  	metadataChunkLength := r.binaryLength()
   105  	if len(serializedData) != metadataChunkLength {
   106  		return NewErrorf(ErrInvalidValue, "Need a slice of exactly %d bytes to serialize this metadata, but got a slice of size %d.", metadataChunkLength, len(serializedData))
   107  	}
   108  
   109  //
   110  //
   111  	cursor := 2
   112  binary.LittleEndian.PutUint16(serializedData[cursor:cursor+2], uint16(metadataChunkLength-chunkPrefixLength)) //
   113  	cursor += 2
   114  
   115  	r.StartTime.binaryPut(serializedData[cursor : cursor+timestampLength])
   116  	cursor += timestampLength
   117  
   118  	binary.LittleEndian.PutUint64(serializedData[cursor:cursor+frequencyLength], r.Frequency)
   119  	cursor += frequencyLength
   120  
   121  //
   122  //
   123  	nameLength := len(r.Name)
   124  	if nameLength > 255 {
   125  		nameLength = 255
   126  	}
   127  	serializedData[cursor] = uint8(nameLength)
   128  	cursor++
   129  	copy(serializedData[cursor:cursor+nameLength], []byte(r.Name[:nameLength]))
   130  	cursor += nameLength
   131  
   132  	copy(serializedData[cursor:cursor+common.AddressLength], r.Owner[:])
   133  	cursor += common.AddressLength
   134  
   135  	return nil
   136  }
   137  
   138  func (r *ResourceMetadata) binaryLength() int {
   139  	return minimumMetadataLength + len(r.Name)
   140  }
   141  
   142  //
   143  //
   144  func (r *ResourceMetadata) serializeAndHash() (rootAddr, metaHash []byte, chunkData []byte, err error) {
   145  
   146  	chunkData = make([]byte, r.binaryLength())
   147  	if err := r.binaryPut(chunkData); err != nil {
   148  		return nil, nil, nil, err
   149  	}
   150  	rootAddr, metaHash = metadataHash(chunkData)
   151  	return rootAddr, metaHash, chunkData, nil
   152  
   153  }
   154  
   155  //
   156  func (metadata *ResourceMetadata) newChunk() (chunk *storage.Chunk, metaHash []byte, err error) {
   157  //
   158  //
   159  //
   160  //
   161  
   162  //
   163  //
   164  //
   165  	rootAddr, metaHash, chunkData, err := metadata.serializeAndHash()
   166  	if err != nil {
   167  		return nil, nil, err
   168  	}
   169  
   170  //
   171  	chunk = storage.NewChunk(rootAddr, nil)
   172  	chunk.SData = chunkData
   173  	chunk.Size = int64(len(chunkData))
   174  
   175  	return chunk, metaHash, nil
   176  }
   177  
   178  //
   179  //
   180  //
   181  //
   182  //
   183  //
   184  //
   185  //
   186  //
   187  //
   188  //
   189  func metadataHash(chunkData []byte) (rootAddr, metaHash []byte) {
   190  	hasher := hashPool.Get().(hash.Hash)
   191  	defer hashPool.Put(hasher)
   192  	hasher.Reset()
   193  	hasher.Write(chunkData[:len(chunkData)-common.AddressLength])
   194  	metaHash = hasher.Sum(nil)
   195  	hasher.Reset()
   196  	hasher.Write(metaHash)
   197  	hasher.Write(chunkData[len(chunkData)-common.AddressLength:])
   198  	rootAddr = hasher.Sum(nil)
   199  	return
   200  }
   201