github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/swarm/storage/mru/update.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 "errors" 30 31 "github.com/ethereum/go-ethereum/swarm/chunk" 32 "github.com/ethereum/go-ethereum/swarm/log" 33 "github.com/ethereum/go-ethereum/swarm/multihash" 34 ) 35 36 // 37 type resourceUpdate struct { 38 updateHeader // 39 data []byte // 40 } 41 42 // 43 // 44 // 45 // 46 const chunkPrefixLength = 2 + 2 47 48 // 49 // 50 // 51 // 52 // 53 const minimumUpdateDataLength = updateHeaderLength + 1 54 const maxUpdateDataLength = chunk.DefaultSize - signatureLength - updateHeaderLength - chunkPrefixLength 55 56 // 57 func (r *resourceUpdate) binaryPut(serializedData []byte) error { 58 datalength := len(r.data) 59 if datalength == 0 { 60 return NewError(ErrInvalidValue, "cannot update a resource with no data") 61 } 62 63 if datalength > maxUpdateDataLength { 64 return NewErrorf(ErrInvalidValue, "data is too big (length=%d). Max length=%d", datalength, maxUpdateDataLength) 65 } 66 67 if len(serializedData) != r.binaryLength() { 68 return NewErrorf(ErrInvalidValue, "slice passed to putBinary must be of exact size. Expected %d bytes", r.binaryLength()) 69 } 70 71 if r.multihash { 72 if _, _, err := multihash.GetMultihashLength(r.data); err != nil { 73 return NewError(ErrInvalidValue, "Invalid multihash") 74 } 75 } 76 77 // 78 cursor := 0 79 binary.LittleEndian.PutUint16(serializedData[cursor:], uint16(updateHeaderLength)) 80 cursor += 2 81 82 // 83 binary.LittleEndian.PutUint16(serializedData[cursor:], uint16(datalength)) 84 cursor += 2 85 86 // 87 if err := r.updateHeader.binaryPut(serializedData[cursor : cursor+updateHeaderLength]); err != nil { 88 return err 89 } 90 cursor += updateHeaderLength 91 92 // 93 copy(serializedData[cursor:], r.data) 94 cursor += datalength 95 96 return nil 97 } 98 99 // 100 func (r *resourceUpdate) binaryLength() int { 101 return chunkPrefixLength + updateHeaderLength + len(r.data) 102 } 103 104 // 105 func (r *resourceUpdate) binaryGet(serializedData []byte) error { 106 if len(serializedData) < minimumUpdateDataLength { 107 return NewErrorf(ErrNothingToReturn, "chunk less than %d bytes cannot be a resource update chunk", minimumUpdateDataLength) 108 } 109 cursor := 0 110 declaredHeaderlength := binary.LittleEndian.Uint16(serializedData[cursor : cursor+2]) 111 if declaredHeaderlength != updateHeaderLength { 112 return NewErrorf(ErrCorruptData, "Invalid header length. Expected %d, got %d", updateHeaderLength, declaredHeaderlength) 113 } 114 115 cursor += 2 116 datalength := int(binary.LittleEndian.Uint16(serializedData[cursor : cursor+2])) 117 cursor += 2 118 119 if chunkPrefixLength+updateHeaderLength+datalength+signatureLength != len(serializedData) { 120 return NewError(ErrNothingToReturn, "length specified in header is different than actual chunk size") 121 } 122 123 // 124 if err := r.updateHeader.binaryGet(serializedData[cursor : cursor+updateHeaderLength]); err != nil { 125 return err 126 } 127 cursor += updateHeaderLength 128 129 data := serializedData[cursor : cursor+datalength] 130 cursor += datalength 131 132 // 133 if r.updateHeader.multihash { 134 mhLength, mhHeaderLength, err := multihash.GetMultihashLength(data) 135 if err != nil { 136 log.Error("multihash parse error", "err", err) 137 return err 138 } 139 if datalength != mhLength+mhHeaderLength { 140 log.Debug("multihash error", "datalength", datalength, "mhLength", mhLength, "mhHeaderLength", mhHeaderLength) 141 return errors.New("Corrupt multihash data") 142 } 143 } 144 145 // 146 r.data = make([]byte, datalength) 147 copy(r.data, data) 148 149 return nil 150 151 } 152 153 // 154 func (r *resourceUpdate) Multihash() bool { 155 return r.multihash 156 }