github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/swarm/storage/feed/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 19:16:44</date>
    10  //</624450119328075776>
    11  
    12  
    13  package feed
    14  
    15  import (
    16  	"bytes"
    17  	"encoding/json"
    18  	"hash"
    19  
    20  	"github.com/ethereum/go-ethereum/common"
    21  	"github.com/ethereum/go-ethereum/common/hexutil"
    22  	"github.com/ethereum/go-ethereum/swarm/storage"
    23  	"github.com/ethereum/go-ethereum/swarm/storage/feed/lookup"
    24  )
    25  
    26  //请求表示对订阅源更新消息进行签名或签名的请求
    27  type Request struct {
    28  Update     //将放在块上的实际内容,较少签名
    29  	Signature  *Signature
    30  idAddr     storage.Address //更新的缓存块地址(未序列化,供内部使用)
    31  binaryData []byte          //缓存的序列化数据(不再序列化!,用于效率/内部使用)
    32  }
    33  
    34  //updateRequestJSON表示JSON序列化的updateRequest
    35  type updateRequestJSON struct {
    36  	ID
    37  	ProtocolVersion uint8  `json:"protocolVersion"`
    38  	Data            string `json:"data,omitempty"`
    39  	Signature       string `json:"signature,omitempty"`
    40  }
    41  
    42  //请求布局
    43  //更新字节
    44  //签名长度字节
    45  const minimumSignedUpdateLength = minimumUpdateDataLength + signatureLength
    46  
    47  //newfirstrequest返回准备好签名的请求以发布第一个源更新
    48  func NewFirstRequest(topic Topic) *Request {
    49  
    50  	request := new(Request)
    51  
    52  //获取当前时间
    53  	now := TimestampProvider.Now().Time
    54  	request.Epoch = lookup.GetFirstEpoch(now)
    55  	request.Feed.Topic = topic
    56  	request.Header.Version = ProtocolVersion
    57  
    58  	return request
    59  }
    60  
    61  //setdata存储提要更新将使用的有效负载数据
    62  func (r *Request) SetData(data []byte) {
    63  	r.data = data
    64  	r.Signature = nil
    65  }
    66  
    67  //如果此请求为签名更新建模,或者为签名请求,则is update返回true
    68  func (r *Request) IsUpdate() bool {
    69  	return r.Signature != nil
    70  }
    71  
    72  //验证签名是否有效
    73  func (r *Request) Verify() (err error) {
    74  	if len(r.data) == 0 {
    75  		return NewError(ErrInvalidValue, "Update does not contain data")
    76  	}
    77  	if r.Signature == nil {
    78  		return NewError(ErrInvalidSignature, "Missing signature field")
    79  	}
    80  
    81  	digest, err := r.GetDigest()
    82  	if err != nil {
    83  		return err
    84  	}
    85  
    86  //获取签名者的地址(它还检查签名是否有效)
    87  	r.Feed.User, err = getUserAddr(digest, *r.Signature)
    88  	if err != nil {
    89  		return err
    90  	}
    91  
    92  //检查块中包含的查找信息是否与updateaddr(块搜索键)匹配。
    93  //用于检索此块的
    94  //如果验证失败,则有人伪造了块。
    95  	if !bytes.Equal(r.idAddr, r.Addr()) {
    96  		return NewError(ErrInvalidSignature, "Signature address does not match with update user address")
    97  	}
    98  
    99  	return nil
   100  }
   101  
   102  //签名执行签名以验证更新消息
   103  func (r *Request) Sign(signer Signer) error {
   104  	r.Feed.User = signer.Address()
   105  r.binaryData = nil           //使序列化数据无效
   106  digest, err := r.GetDigest() //计算摘要并序列化为.BinaryData
   107  	if err != nil {
   108  		return err
   109  	}
   110  
   111  	signature, err := signer.Sign(digest)
   112  	if err != nil {
   113  		return err
   114  	}
   115  
   116  //尽管签名者接口返回签名者的公共地址,
   117  //从签名中恢复它以查看它们是否匹配
   118  	userAddr, err := getUserAddr(digest, signature)
   119  	if err != nil {
   120  		return NewError(ErrInvalidSignature, "Error verifying signature")
   121  	}
   122  
   123  if userAddr != signer.Address() { //健全性检查以确保签名者声明的地址与用于签名的地址相同!
   124  		return NewError(ErrInvalidSignature, "Signer address does not match update user address")
   125  	}
   126  
   127  	r.Signature = &signature
   128  	r.idAddr = r.Addr()
   129  	return nil
   130  }
   131  
   132  //GetDigest创建用于签名的源更新摘要
   133  //序列化的负载缓存在.BinaryData中
   134  func (r *Request) GetDigest() (result common.Hash, err error) {
   135  	hasher := hashPool.Get().(hash.Hash)
   136  	defer hashPool.Put(hasher)
   137  	hasher.Reset()
   138  	dataLength := r.Update.binaryLength()
   139  	if r.binaryData == nil {
   140  		r.binaryData = make([]byte, dataLength+signatureLength)
   141  		if err := r.Update.binaryPut(r.binaryData[:dataLength]); err != nil {
   142  			return result, err
   143  		}
   144  	}
   145  hasher.Write(r.binaryData[:dataLength]) //除了签名以外的一切。
   146  
   147  	return common.BytesToHash(hasher.Sum(nil)), nil
   148  }
   149  
   150  //创建更新块。
   151  func (r *Request) toChunk() (storage.Chunk, error) {
   152  
   153  //检查更新是否已签名和序列化
   154  //为了提高效率,数据在签名期间序列化并缓存在
   155  //在.getDigest()中计算签名摘要时的BinaryData字段
   156  	if r.Signature == nil || r.binaryData == nil {
   157  		return nil, NewError(ErrInvalidSignature, "toChunk called without a valid signature or payload data. Call .Sign() first.")
   158  	}
   159  
   160  	updateLength := r.Update.binaryLength()
   161  
   162  //签名是块数据中的最后一项
   163  	copy(r.binaryData[updateLength:], r.Signature[:])
   164  
   165  	chunk := storage.NewChunk(r.idAddr, r.binaryData)
   166  	return chunk, nil
   167  }
   168  
   169  //FromChunk从块数据填充此结构。它不验证签名是否有效。
   170  func (r *Request) fromChunk(chunk storage.Chunk) error {
   171  //有关更新块布局,请参见请求定义
   172  
   173  	chunkdata := chunk.Data()
   174  
   175  //反序列化源更新部分
   176  	if err := r.Update.binaryGet(chunkdata[:len(chunkdata)-signatureLength]); err != nil {
   177  		return err
   178  	}
   179  
   180  //提取签名
   181  	var signature *Signature
   182  	cursor := r.Update.binaryLength()
   183  	sigdata := chunkdata[cursor : cursor+signatureLength]
   184  	if len(sigdata) > 0 {
   185  		signature = &Signature{}
   186  		copy(signature[:], sigdata)
   187  	}
   188  
   189  	r.Signature = signature
   190  	r.idAddr = chunk.Address()
   191  	r.binaryData = chunkdata
   192  
   193  	return nil
   194  
   195  }
   196  
   197  //FromValues从字符串键值存储中反序列化此实例
   198  //用于分析查询字符串
   199  func (r *Request) FromValues(values Values, data []byte) error {
   200  	signatureBytes, err := hexutil.Decode(values.Get("signature"))
   201  	if err != nil {
   202  		r.Signature = nil
   203  	} else {
   204  		if len(signatureBytes) != signatureLength {
   205  			return NewError(ErrInvalidSignature, "Incorrect signature length")
   206  		}
   207  		r.Signature = new(Signature)
   208  		copy(r.Signature[:], signatureBytes)
   209  	}
   210  	err = r.Update.FromValues(values, data)
   211  	if err != nil {
   212  		return err
   213  	}
   214  	r.idAddr = r.Addr()
   215  	return err
   216  }
   217  
   218  //AppendValues将此结构序列化到提供的字符串键值存储区中
   219  //用于生成查询字符串
   220  func (r *Request) AppendValues(values Values) []byte {
   221  	if r.Signature != nil {
   222  		values.Set("signature", hexutil.Encode(r.Signature[:]))
   223  	}
   224  	return r.Update.AppendValues(values)
   225  }
   226  
   227  //fromjson接受更新请求json并填充更新请求
   228  func (r *Request) fromJSON(j *updateRequestJSON) error {
   229  
   230  	r.ID = j.ID
   231  	r.Header.Version = j.ProtocolVersion
   232  
   233  	var err error
   234  	if j.Data != "" {
   235  		r.data, err = hexutil.Decode(j.Data)
   236  		if err != nil {
   237  			return NewError(ErrInvalidValue, "Cannot decode data")
   238  		}
   239  	}
   240  
   241  	if j.Signature != "" {
   242  		sigBytes, err := hexutil.Decode(j.Signature)
   243  		if err != nil || len(sigBytes) != signatureLength {
   244  			return NewError(ErrInvalidSignature, "Cannot decode signature")
   245  		}
   246  		r.Signature = new(Signature)
   247  		r.idAddr = r.Addr()
   248  		copy(r.Signature[:], sigBytes)
   249  	}
   250  	return nil
   251  }
   252  
   253  //unmarshaljson接受存储在字节数组中的json结构并填充请求对象
   254  //实现json.unmasheler接口
   255  func (r *Request) UnmarshalJSON(rawData []byte) error {
   256  	var requestJSON updateRequestJSON
   257  	if err := json.Unmarshal(rawData, &requestJSON); err != nil {
   258  		return err
   259  	}
   260  	return r.fromJSON(&requestJSON)
   261  }
   262  
   263  //marshaljson接受更新请求并将其作为json结构编码到字节数组中
   264  //实现json.Marshaler接口
   265  func (r *Request) MarshalJSON() (rawData []byte, err error) {
   266  	var signatureString, dataString string
   267  	if r.Signature != nil {
   268  		signatureString = hexutil.Encode(r.Signature[:])
   269  	}
   270  	if r.data != nil {
   271  		dataString = hexutil.Encode(r.data)
   272  	}
   273  
   274  	requestJSON := &updateRequestJSON{
   275  		ID:              r.ID,
   276  		ProtocolVersion: r.Header.Version,
   277  		Data:            dataString,
   278  		Signature:       signatureString,
   279  	}
   280  
   281  	return json.Marshal(requestJSON)
   282  }
   283