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