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  }