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