github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/swarm/storage/mru/request.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  //</624342683355189248>
    11  
    12  //
    13  //
    14  //
    15  //
    16  //
    17  //
    18  //
    19  //
    20  //
    21  //
    22  //
    23  //
    24  //
    25  //
    26  //
    27  
    28  package mru
    29  
    30  import (
    31  	"bytes"
    32  	"encoding/json"
    33  
    34  	"github.com/ethereum/go-ethereum/common"
    35  	"github.com/ethereum/go-ethereum/common/hexutil"
    36  	"github.com/ethereum/go-ethereum/swarm/storage"
    37  )
    38  
    39  //
    40  type updateRequestJSON struct {
    41  	Name      string `json:"name,omitempty"`
    42  	Frequency uint64 `json:"frequency,omitempty"`
    43  	StartTime uint64 `json:"startTime,omitempty"`
    44  	Owner     string `json:"ownerAddr,omitempty"`
    45  	RootAddr  string `json:"rootAddr,omitempty"`
    46  	MetaHash  string `json:"metaHash,omitempty"`
    47  	Version   uint32 `json:"version,omitempty"`
    48  	Period    uint32 `json:"period,omitempty"`
    49  	Data      string `json:"data,omitempty"`
    50  	Multihash bool   `json:"multiHash"`
    51  	Signature string `json:"signature,omitempty"`
    52  }
    53  
    54  //
    55  type Request struct {
    56  	SignedResourceUpdate
    57  	metadata ResourceMetadata
    58  	isNew    bool
    59  }
    60  
    61  var zeroAddr = common.Address{}
    62  
    63  //
    64  func NewCreateUpdateRequest(metadata *ResourceMetadata) (*Request, error) {
    65  
    66  	request, err := NewCreateRequest(metadata)
    67  	if err != nil {
    68  		return nil, err
    69  	}
    70  
    71  //
    72  	now := TimestampProvider.Now().Time
    73  
    74  	request.version = 1
    75  	request.period, err = getNextPeriod(metadata.StartTime.Time, now, metadata.Frequency)
    76  	if err != nil {
    77  		return nil, err
    78  	}
    79  	return request, nil
    80  }
    81  
    82  //
    83  func NewCreateRequest(metadata *ResourceMetadata) (request *Request, err error) {
    84  if metadata.StartTime.Time == 0 { //
    85  		metadata.StartTime = TimestampProvider.Now()
    86  	}
    87  
    88  	if metadata.Owner == zeroAddr {
    89  		return nil, NewError(ErrInvalidValue, "OwnerAddr is not set")
    90  	}
    91  
    92  	request = &Request{
    93  		metadata: *metadata,
    94  	}
    95  	request.rootAddr, request.metaHash, _, err = request.metadata.serializeAndHash()
    96  	request.isNew = true
    97  	return request, nil
    98  }
    99  
   100  //
   101  func (r *Request) Frequency() uint64 {
   102  	return r.metadata.Frequency
   103  }
   104  
   105  //
   106  func (r *Request) Name() string {
   107  	return r.metadata.Name
   108  }
   109  
   110  //
   111  func (r *Request) Multihash() bool {
   112  	return r.multihash
   113  }
   114  
   115  //
   116  func (r *Request) Period() uint32 {
   117  	return r.period
   118  }
   119  
   120  //
   121  func (r *Request) Version() uint32 {
   122  	return r.version
   123  }
   124  
   125  //
   126  func (r *Request) RootAddr() storage.Address {
   127  	return r.rootAddr
   128  }
   129  
   130  //
   131  func (r *Request) StartTime() Timestamp {
   132  	return r.metadata.StartTime
   133  }
   134  
   135  //
   136  func (r *Request) Owner() common.Address {
   137  	return r.metadata.Owner
   138  }
   139  
   140  //
   141  func (r *Request) Sign(signer Signer) error {
   142  	if r.metadata.Owner != zeroAddr && r.metadata.Owner != signer.Address() {
   143  		return NewError(ErrInvalidSignature, "Signer does not match current owner of the resource")
   144  	}
   145  
   146  	if err := r.SignedResourceUpdate.Sign(signer); err != nil {
   147  		return err
   148  	}
   149  	r.metadata.Owner = signer.Address()
   150  	return nil
   151  }
   152  
   153  //
   154  func (r *Request) SetData(data []byte, multihash bool) {
   155  	r.data = data
   156  	r.multihash = multihash
   157  	r.signature = nil
   158  	if !r.isNew {
   159  r.metadata.Frequency = 0 //
   160  	}
   161  }
   162  
   163  func (r *Request) IsNew() bool {
   164  	return r.metadata.Frequency > 0 && (r.period <= 1 || r.version <= 1)
   165  }
   166  
   167  func (r *Request) IsUpdate() bool {
   168  	return r.signature != nil
   169  }
   170  
   171  //
   172  func (r *Request) fromJSON(j *updateRequestJSON) error {
   173  
   174  	r.version = j.Version
   175  	r.period = j.Period
   176  	r.multihash = j.Multihash
   177  	r.metadata.Name = j.Name
   178  	r.metadata.Frequency = j.Frequency
   179  	r.metadata.StartTime.Time = j.StartTime
   180  
   181  	if err := decodeHexArray(r.metadata.Owner[:], j.Owner, "ownerAddr"); err != nil {
   182  		return err
   183  	}
   184  
   185  	var err error
   186  	if j.Data != "" {
   187  		r.data, err = hexutil.Decode(j.Data)
   188  		if err != nil {
   189  			return NewError(ErrInvalidValue, "Cannot decode data")
   190  		}
   191  	}
   192  
   193  	var declaredRootAddr storage.Address
   194  	var declaredMetaHash []byte
   195  
   196  	declaredRootAddr, err = decodeHexSlice(j.RootAddr, storage.KeyLength, "rootAddr")
   197  	if err != nil {
   198  		return err
   199  	}
   200  	declaredMetaHash, err = decodeHexSlice(j.MetaHash, 32, "metaHash")
   201  	if err != nil {
   202  		return err
   203  	}
   204  
   205  	if r.IsNew() {
   206  //
   207  //
   208  //
   209  
   210  		r.rootAddr, r.metaHash, _, err = r.metadata.serializeAndHash()
   211  		if err != nil {
   212  			return err
   213  		}
   214  		if j.RootAddr != "" && !bytes.Equal(declaredRootAddr, r.rootAddr) {
   215  			return NewError(ErrInvalidValue, "rootAddr does not match resource metadata")
   216  		}
   217  		if j.MetaHash != "" && !bytes.Equal(declaredMetaHash, r.metaHash) {
   218  			return NewError(ErrInvalidValue, "metaHash does not match resource metadata")
   219  		}
   220  
   221  	} else {
   222  //
   223  		r.rootAddr = declaredRootAddr
   224  		r.metaHash = declaredMetaHash
   225  	}
   226  
   227  	if j.Signature != "" {
   228  		sigBytes, err := hexutil.Decode(j.Signature)
   229  		if err != nil || len(sigBytes) != signatureLength {
   230  			return NewError(ErrInvalidSignature, "Cannot decode signature")
   231  		}
   232  		r.signature = new(Signature)
   233  		r.updateAddr = r.UpdateAddr()
   234  		copy(r.signature[:], sigBytes)
   235  	}
   236  	return nil
   237  }
   238  
   239  func decodeHexArray(dst []byte, src, name string) error {
   240  	bytes, err := decodeHexSlice(src, len(dst), name)
   241  	if err != nil {
   242  		return err
   243  	}
   244  	if bytes != nil {
   245  		copy(dst, bytes)
   246  	}
   247  	return nil
   248  }
   249  
   250  func decodeHexSlice(src string, expectedLength int, name string) (bytes []byte, err error) {
   251  	if src != "" {
   252  		bytes, err = hexutil.Decode(src)
   253  		if err != nil || len(bytes) != expectedLength {
   254  			return nil, NewErrorf(ErrInvalidValue, "Cannot decode %s", name)
   255  		}
   256  	}
   257  	return bytes, nil
   258  }
   259  
   260  //
   261  //
   262  func (r *Request) UnmarshalJSON(rawData []byte) error {
   263  	var requestJSON updateRequestJSON
   264  	if err := json.Unmarshal(rawData, &requestJSON); err != nil {
   265  		return err
   266  	}
   267  	return r.fromJSON(&requestJSON)
   268  }
   269  
   270  //
   271  //
   272  func (r *Request) MarshalJSON() (rawData []byte, err error) {
   273  	var signatureString, dataHashString, rootAddrString, metaHashString string
   274  	if r.signature != nil {
   275  		signatureString = hexutil.Encode(r.signature[:])
   276  	}
   277  	if r.data != nil {
   278  		dataHashString = hexutil.Encode(r.data)
   279  	}
   280  	if r.rootAddr != nil {
   281  		rootAddrString = hexutil.Encode(r.rootAddr)
   282  	}
   283  	if r.metaHash != nil {
   284  		metaHashString = hexutil.Encode(r.metaHash)
   285  	}
   286  	var ownerAddrString string
   287  	if r.metadata.Frequency == 0 {
   288  		ownerAddrString = ""
   289  	} else {
   290  		ownerAddrString = hexutil.Encode(r.metadata.Owner[:])
   291  	}
   292  
   293  	requestJSON := &updateRequestJSON{
   294  		Name:      r.metadata.Name,
   295  		Frequency: r.metadata.Frequency,
   296  		StartTime: r.metadata.StartTime.Time,
   297  		Version:   r.version,
   298  		Period:    r.period,
   299  		Owner:     ownerAddrString,
   300  		Data:      dataHashString,
   301  		Multihash: r.multihash,
   302  		Signature: signatureString,
   303  		RootAddr:  rootAddrString,
   304  		MetaHash:  metaHashString,
   305  	}
   306  
   307  	return json.Marshal(requestJSON)
   308  }
   309