github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/swarm/storage/mru/metadata.go (about)

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