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 }