github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/les/odr_requests.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:39</date> 10 //</624450095609286656> 11 12 13 //package light实现可按需检索的状态和链对象 14 //对于以太坊Light客户端。 15 package les 16 17 import ( 18 "encoding/binary" 19 "errors" 20 "fmt" 21 22 "github.com/ethereum/go-ethereum/common" 23 "github.com/ethereum/go-ethereum/core/rawdb" 24 "github.com/ethereum/go-ethereum/core/types" 25 "github.com/ethereum/go-ethereum/crypto" 26 "github.com/ethereum/go-ethereum/ethdb" 27 "github.com/ethereum/go-ethereum/light" 28 "github.com/ethereum/go-ethereum/log" 29 "github.com/ethereum/go-ethereum/rlp" 30 "github.com/ethereum/go-ethereum/trie" 31 ) 32 33 var ( 34 errInvalidMessageType = errors.New("invalid message type") 35 errInvalidEntryCount = errors.New("invalid number of response entries") 36 errHeaderUnavailable = errors.New("header unavailable") 37 errTxHashMismatch = errors.New("transaction hash mismatch") 38 errUncleHashMismatch = errors.New("uncle hash mismatch") 39 errReceiptHashMismatch = errors.New("receipt hash mismatch") 40 errDataHashMismatch = errors.New("data hash mismatch") 41 errCHTHashMismatch = errors.New("cht hash mismatch") 42 errCHTNumberMismatch = errors.New("cht number mismatch") 43 errUselessNodes = errors.New("useless nodes in merkle proof nodeset") 44 ) 45 46 type LesOdrRequest interface { 47 GetCost(*peer) uint64 48 CanSend(*peer) bool 49 Request(uint64, *peer) error 50 Validate(ethdb.Database, *Msg) error 51 } 52 53 func LesRequest(req light.OdrRequest) LesOdrRequest { 54 switch r := req.(type) { 55 case *light.BlockRequest: 56 return (*BlockRequest)(r) 57 case *light.ReceiptsRequest: 58 return (*ReceiptsRequest)(r) 59 case *light.TrieRequest: 60 return (*TrieRequest)(r) 61 case *light.CodeRequest: 62 return (*CodeRequest)(r) 63 case *light.ChtRequest: 64 return (*ChtRequest)(r) 65 case *light.BloomRequest: 66 return (*BloomRequest)(r) 67 default: 68 return nil 69 } 70 } 71 72 //BlockRequest是块体的ODR请求类型 73 type BlockRequest light.BlockRequest 74 75 //getcost根据服务返回给定ODR请求的成本 76 //同行成本表(lesodrequest的实现) 77 func (r *BlockRequest) GetCost(peer *peer) uint64 { 78 return peer.GetRequestCost(GetBlockBodiesMsg, 1) 79 } 80 81 //cansend告诉某个对等机是否适合服务于给定的请求 82 func (r *BlockRequest) CanSend(peer *peer) bool { 83 return peer.HasBlock(r.Hash, r.Number, false) 84 } 85 86 //请求向LES网络发送一个ODR请求(LESODRREQUEST的实现) 87 func (r *BlockRequest) Request(reqID uint64, peer *peer) error { 88 peer.Log().Debug("Requesting block body", "hash", r.Hash) 89 return peer.RequestBodies(reqID, r.GetCost(peer), []common.Hash{r.Hash}) 90 } 91 92 //有效处理来自LES网络的ODR请求回复消息 93 //returns true and stores results in memory if the message was a valid reply 94 //到请求(lesodrequest的实现) 95 func (r *BlockRequest) Validate(db ethdb.Database, msg *Msg) error { 96 log.Debug("Validating block body", "hash", r.Hash) 97 98 //确保我们有一个正确的信息与一个单一的块体 99 if msg.MsgType != MsgBlockBodies { 100 return errInvalidMessageType 101 } 102 bodies := msg.Obj.([]*types.Body) 103 if len(bodies) != 1 { 104 return errInvalidEntryCount 105 } 106 body := bodies[0] 107 108 //检索存储的头并根据它验证块内容 109 header := rawdb.ReadHeader(db, r.Hash, r.Number) 110 if header == nil { 111 return errHeaderUnavailable 112 } 113 if header.TxHash != types.DeriveSha(types.Transactions(body.Transactions)) { 114 return errTxHashMismatch 115 } 116 if header.UncleHash != types.CalcUncleHash(body.Uncles) { 117 return errUncleHashMismatch 118 } 119 //Validations passed, encode and store RLP 120 data, err := rlp.EncodeToBytes(body) 121 if err != nil { 122 return err 123 } 124 r.Rlp = data 125 return nil 126 } 127 128 //ReceiptsRequest是按块哈希列出的块接收的ODR请求类型 129 type ReceiptsRequest light.ReceiptsRequest 130 131 //getcost根据服务返回给定ODR请求的成本 132 //同行成本表(lesodrequest的实现) 133 func (r *ReceiptsRequest) GetCost(peer *peer) uint64 { 134 return peer.GetRequestCost(GetReceiptsMsg, 1) 135 } 136 137 //cansend告诉某个对等机是否适合服务于给定的请求 138 func (r *ReceiptsRequest) CanSend(peer *peer) bool { 139 return peer.HasBlock(r.Hash, r.Number, false) 140 } 141 142 //请求向LES网络发送一个ODR请求(LESODRREQUEST的实现) 143 func (r *ReceiptsRequest) Request(reqID uint64, peer *peer) error { 144 peer.Log().Debug("Requesting block receipts", "hash", r.Hash) 145 return peer.RequestReceipts(reqID, r.GetCost(peer), []common.Hash{r.Hash}) 146 } 147 148 //有效处理来自LES网络的ODR请求回复消息 149 //如果消息是有效的答复,则返回true并将结果存储在内存中 150 //到请求(lesodrequest的实现) 151 func (r *ReceiptsRequest) Validate(db ethdb.Database, msg *Msg) error { 152 log.Debug("Validating block receipts", "hash", r.Hash) 153 154 //确保我们有一个正确的消息和一个单块收据 155 if msg.MsgType != MsgReceipts { 156 return errInvalidMessageType 157 } 158 receipts := msg.Obj.([]types.Receipts) 159 if len(receipts) != 1 { 160 return errInvalidEntryCount 161 } 162 receipt := receipts[0] 163 164 //检索存储的标题并根据其验证收据内容 165 header := rawdb.ReadHeader(db, r.Hash, r.Number) 166 if header == nil { 167 return errHeaderUnavailable 168 } 169 if header.ReceiptHash != types.DeriveSha(receipt) { 170 return errReceiptHashMismatch 171 } 172 //验证通过,存储并返回 173 r.Receipts = receipt 174 return nil 175 } 176 177 type ProofReq struct { 178 BHash common.Hash 179 AccKey, Key []byte 180 FromLevel uint 181 } 182 183 //状态/存储trie项的ODR请求类型,请参见leSodrRequest接口 184 type TrieRequest light.TrieRequest 185 186 //getcost根据服务返回给定ODR请求的成本 187 //同行成本表(lesodrequest的实现) 188 func (r *TrieRequest) GetCost(peer *peer) uint64 { 189 switch peer.version { 190 case lpv1: 191 return peer.GetRequestCost(GetProofsV1Msg, 1) 192 case lpv2: 193 return peer.GetRequestCost(GetProofsV2Msg, 1) 194 default: 195 panic(nil) 196 } 197 } 198 199 //cansend告诉某个对等机是否适合服务于给定的请求 200 func (r *TrieRequest) CanSend(peer *peer) bool { 201 return peer.HasBlock(r.Id.BlockHash, r.Id.BlockNumber, true) 202 } 203 204 //请求向LES网络发送一个ODR请求(LESODRREQUEST的实现) 205 func (r *TrieRequest) Request(reqID uint64, peer *peer) error { 206 peer.Log().Debug("Requesting trie proof", "root", r.Id.Root, "key", r.Key) 207 req := ProofReq{ 208 BHash: r.Id.BlockHash, 209 AccKey: r.Id.AccKey, 210 Key: r.Key, 211 } 212 return peer.RequestProofs(reqID, r.GetCost(peer), []ProofReq{req}) 213 } 214 215 //有效处理来自LES网络的ODR请求回复消息 216 //如果消息是有效的答复,则返回true并将结果存储在内存中 217 //到请求(lesodrequest的实现) 218 func (r *TrieRequest) Validate(db ethdb.Database, msg *Msg) error { 219 log.Debug("Validating trie proof", "root", r.Id.Root, "key", r.Key) 220 221 switch msg.MsgType { 222 case MsgProofsV1: 223 proofs := msg.Obj.([]light.NodeList) 224 if len(proofs) != 1 { 225 return errInvalidEntryCount 226 } 227 nodeSet := proofs[0].NodeSet() 228 //验证证明,如果签出则保存 229 if _, _, err := trie.VerifyProof(r.Id.Root, r.Key, nodeSet); err != nil { 230 return fmt.Errorf("merkle proof verification failed: %v", err) 231 } 232 r.Proof = nodeSet 233 return nil 234 235 case MsgProofsV2: 236 proofs := msg.Obj.(light.NodeList) 237 //验证证明,如果签出则保存 238 nodeSet := proofs.NodeSet() 239 reads := &readTraceDB{db: nodeSet} 240 if _, _, err := trie.VerifyProof(r.Id.Root, r.Key, reads); err != nil { 241 return fmt.Errorf("merkle proof verification failed: %v", err) 242 } 243 //检查VerifyProof是否已读取所有节点 244 if len(reads.reads) != nodeSet.KeyCount() { 245 return errUselessNodes 246 } 247 r.Proof = nodeSet 248 return nil 249 250 default: 251 return errInvalidMessageType 252 } 253 } 254 255 type CodeReq struct { 256 BHash common.Hash 257 AccKey []byte 258 } 259 260 //节点数据的ODR请求类型(用于检索合同代码),请参见LESODRREQUEST接口 261 type CodeRequest light.CodeRequest 262 263 //getcost根据服务返回给定ODR请求的成本 264 //同行成本表(lesodrequest的实现) 265 func (r *CodeRequest) GetCost(peer *peer) uint64 { 266 return peer.GetRequestCost(GetCodeMsg, 1) 267 } 268 269 //cansend告诉某个对等机是否适合服务于给定的请求 270 func (r *CodeRequest) CanSend(peer *peer) bool { 271 return peer.HasBlock(r.Id.BlockHash, r.Id.BlockNumber, true) 272 } 273 274 //请求向LES网络发送一个ODR请求(LESODRREQUEST的实现) 275 func (r *CodeRequest) Request(reqID uint64, peer *peer) error { 276 peer.Log().Debug("Requesting code data", "hash", r.Hash) 277 req := CodeReq{ 278 BHash: r.Id.BlockHash, 279 AccKey: r.Id.AccKey, 280 } 281 return peer.RequestCode(reqID, r.GetCost(peer), []CodeReq{req}) 282 } 283 284 //有效处理来自LES网络的ODR请求回复消息 285 //如果消息是有效的答复,则返回true并将结果存储在内存中 286 //到请求(lesodrequest的实现) 287 func (r *CodeRequest) Validate(db ethdb.Database, msg *Msg) error { 288 log.Debug("Validating code data", "hash", r.Hash) 289 290 //确保我们有一个带有单个代码元素的正确消息 291 if msg.MsgType != MsgCode { 292 return errInvalidMessageType 293 } 294 reply := msg.Obj.([][]byte) 295 if len(reply) != 1 { 296 return errInvalidEntryCount 297 } 298 data := reply[0] 299 300 //验证数据并存储是否签出 301 if hash := crypto.Keccak256Hash(data); r.Hash != hash { 302 return errDataHashMismatch 303 } 304 r.Data = data 305 return nil 306 } 307 308 const ( 309 //helper trie类型常量 310 htCanonical = iota //规范哈希trie 311 htBloomBits //布卢姆斯特里 312 313 //适用于所有helper trie请求 314 auxRoot = 1 315 //适用于htcanonical 316 auxHeader = 2 317 ) 318 319 type HelperTrieReq struct { 320 Type uint 321 TrieIdx uint64 322 Key []byte 323 FromLevel, AuxReq uint 324 } 325 326 type HelperTrieResps struct { //描述所有响应,而不仅仅是单个响应 327 Proofs light.NodeList 328 AuxData [][]byte 329 } 330 331 //遗产LES / 1 332 type ChtReq struct { 333 ChtNum, BlockNum uint64 334 FromLevel uint 335 } 336 337 //遗产LES / 1 338 type ChtResp struct { 339 Header *types.Header 340 Proof []rlp.RawValue 341 } 342 343 //ODR request type for requesting headers by Canonical Hash Trie, see LesOdrRequest interface 344 type ChtRequest light.ChtRequest 345 346 //getcost根据服务返回给定ODR请求的成本 347 //同行成本表(lesodrequest的实现) 348 func (r *ChtRequest) GetCost(peer *peer) uint64 { 349 switch peer.version { 350 case lpv1: 351 return peer.GetRequestCost(GetHeaderProofsMsg, 1) 352 case lpv2: 353 return peer.GetRequestCost(GetHelperTrieProofsMsg, 1) 354 default: 355 panic(nil) 356 } 357 } 358 359 //cansend告诉某个对等机是否适合服务于给定的请求 360 func (r *ChtRequest) CanSend(peer *peer) bool { 361 peer.lock.RLock() 362 defer peer.lock.RUnlock() 363 364 return peer.headInfo.Number >= r.Config.ChtConfirms && r.ChtNum <= (peer.headInfo.Number-r.Config.ChtConfirms)/r.Config.ChtSize 365 } 366 367 //请求向LES网络发送一个ODR请求(LESODRREQUEST的实现) 368 func (r *ChtRequest) Request(reqID uint64, peer *peer) error { 369 peer.Log().Debug("Requesting CHT", "cht", r.ChtNum, "block", r.BlockNum) 370 var encNum [8]byte 371 binary.BigEndian.PutUint64(encNum[:], r.BlockNum) 372 req := HelperTrieReq{ 373 Type: htCanonical, 374 TrieIdx: r.ChtNum, 375 Key: encNum[:], 376 AuxReq: auxHeader, 377 } 378 switch peer.version { 379 case lpv1: 380 var reqsV1 ChtReq 381 if req.Type != htCanonical || req.AuxReq != auxHeader || len(req.Key) != 8 { 382 return fmt.Errorf("Request invalid in LES/1 mode") 383 } 384 blockNum := binary.BigEndian.Uint64(req.Key) 385 //将helpertrie请求转换为旧的cht请求 386 reqsV1 = ChtReq{ChtNum: (req.TrieIdx + 1) * (r.Config.ChtSize / r.Config.PairChtSize), BlockNum: blockNum, FromLevel: req.FromLevel} 387 return peer.RequestHelperTrieProofs(reqID, r.GetCost(peer), []ChtReq{reqsV1}) 388 case lpv2: 389 return peer.RequestHelperTrieProofs(reqID, r.GetCost(peer), []HelperTrieReq{req}) 390 default: 391 panic(nil) 392 } 393 } 394 395 //有效处理来自LES网络的ODR请求回复消息 396 //如果消息是有效的答复,则返回true并将结果存储在内存中 397 //到请求(lesodrequest的实现) 398 func (r *ChtRequest) Validate(db ethdb.Database, msg *Msg) error { 399 log.Debug("Validating CHT", "cht", r.ChtNum, "block", r.BlockNum) 400 401 switch msg.MsgType { 402 case MsgHeaderProofs: //LES/1向后兼容性 403 proofs := msg.Obj.([]ChtResp) 404 if len(proofs) != 1 { 405 return errInvalidEntryCount 406 } 407 proof := proofs[0] 408 409 //验证CHT 410 var encNumber [8]byte 411 binary.BigEndian.PutUint64(encNumber[:], r.BlockNum) 412 413 value, _, err := trie.VerifyProof(r.ChtRoot, encNumber[:], light.NodeList(proof.Proof).NodeSet()) 414 if err != nil { 415 return err 416 } 417 var node light.ChtNode 418 if err := rlp.DecodeBytes(value, &node); err != nil { 419 return err 420 } 421 if node.Hash != proof.Header.Hash() { 422 return errCHTHashMismatch 423 } 424 //验证通过,存储并返回 425 r.Header = proof.Header 426 r.Proof = light.NodeList(proof.Proof).NodeSet() 427 r.Td = node.Td 428 case MsgHelperTrieProofs: 429 resp := msg.Obj.(HelperTrieResps) 430 if len(resp.AuxData) != 1 { 431 return errInvalidEntryCount 432 } 433 nodeSet := resp.Proofs.NodeSet() 434 headerEnc := resp.AuxData[0] 435 if len(headerEnc) == 0 { 436 return errHeaderUnavailable 437 } 438 header := new(types.Header) 439 if err := rlp.DecodeBytes(headerEnc, header); err != nil { 440 return errHeaderUnavailable 441 } 442 443 //验证CHT 444 var encNumber [8]byte 445 binary.BigEndian.PutUint64(encNumber[:], r.BlockNum) 446 447 reads := &readTraceDB{db: nodeSet} 448 value, _, err := trie.VerifyProof(r.ChtRoot, encNumber[:], reads) 449 if err != nil { 450 return fmt.Errorf("merkle proof verification failed: %v", err) 451 } 452 if len(reads.reads) != nodeSet.KeyCount() { 453 return errUselessNodes 454 } 455 456 var node light.ChtNode 457 if err := rlp.DecodeBytes(value, &node); err != nil { 458 return err 459 } 460 if node.Hash != header.Hash() { 461 return errCHTHashMismatch 462 } 463 if r.BlockNum != header.Number.Uint64() { 464 return errCHTNumberMismatch 465 } 466 //验证通过,存储并返回 467 r.Header = header 468 r.Proof = nodeSet 469 r.Td = node.Td 470 default: 471 return errInvalidMessageType 472 } 473 return nil 474 } 475 476 type BloomReq struct { 477 BloomTrieNum, BitIdx, SectionIndex, FromLevel uint64 478 } 479 480 //用于通过规范哈希检索请求头的ODR请求类型,请参见leSodrRequest接口 481 type BloomRequest light.BloomRequest 482 483 //getcost根据服务返回给定ODR请求的成本 484 //同行成本表(lesodrequest的实现) 485 func (r *BloomRequest) GetCost(peer *peer) uint64 { 486 return peer.GetRequestCost(GetHelperTrieProofsMsg, len(r.SectionIndexList)) 487 } 488 489 //cansend告诉某个对等机是否适合服务于给定的请求 490 func (r *BloomRequest) CanSend(peer *peer) bool { 491 peer.lock.RLock() 492 defer peer.lock.RUnlock() 493 494 if peer.version < lpv2 { 495 return false 496 } 497 return peer.headInfo.Number >= r.Config.BloomTrieConfirms && r.BloomTrieNum <= (peer.headInfo.Number-r.Config.BloomTrieConfirms)/r.Config.BloomTrieSize 498 } 499 500 //请求向LES网络发送一个ODR请求(LESODRREQUEST的实现) 501 func (r *BloomRequest) Request(reqID uint64, peer *peer) error { 502 peer.Log().Debug("Requesting BloomBits", "bloomTrie", r.BloomTrieNum, "bitIdx", r.BitIdx, "sections", r.SectionIndexList) 503 reqs := make([]HelperTrieReq, len(r.SectionIndexList)) 504 505 var encNumber [10]byte 506 binary.BigEndian.PutUint16(encNumber[:2], uint16(r.BitIdx)) 507 508 for i, sectionIdx := range r.SectionIndexList { 509 binary.BigEndian.PutUint64(encNumber[2:], sectionIdx) 510 reqs[i] = HelperTrieReq{ 511 Type: htBloomBits, 512 TrieIdx: r.BloomTrieNum, 513 Key: common.CopyBytes(encNumber[:]), 514 } 515 } 516 return peer.RequestHelperTrieProofs(reqID, r.GetCost(peer), reqs) 517 } 518 519 //有效处理来自LES网络的ODR请求回复消息 520 //如果消息是有效的答复,则返回true并将结果存储在内存中 521 //到请求(lesodrequest的实现) 522 func (r *BloomRequest) Validate(db ethdb.Database, msg *Msg) error { 523 log.Debug("Validating BloomBits", "bloomTrie", r.BloomTrieNum, "bitIdx", r.BitIdx, "sections", r.SectionIndexList) 524 525 //确保我们有一个正确的消息和一个证明元素 526 if msg.MsgType != MsgHelperTrieProofs { 527 return errInvalidMessageType 528 } 529 resps := msg.Obj.(HelperTrieResps) 530 proofs := resps.Proofs 531 nodeSet := proofs.NodeSet() 532 reads := &readTraceDB{db: nodeSet} 533 534 r.BloomBits = make([][]byte, len(r.SectionIndexList)) 535 536 //核实证据 537 var encNumber [10]byte 538 binary.BigEndian.PutUint16(encNumber[:2], uint16(r.BitIdx)) 539 540 for i, idx := range r.SectionIndexList { 541 binary.BigEndian.PutUint64(encNumber[2:], idx) 542 value, _, err := trie.VerifyProof(r.BloomTrieRoot, encNumber[:], reads) 543 if err != nil { 544 return err 545 } 546 r.BloomBits[i] = value 547 } 548 549 if len(reads.reads) != nodeSet.KeyCount() { 550 return errUselessNodes 551 } 552 r.Proofs = nodeSet 553 return nil 554 } 555 556 //readTraceDB stores the keys of database reads. We use this to check that received node 557 //集合只包含使证明通过所需的trie节点。 558 type readTraceDB struct { 559 db trie.DatabaseReader 560 reads map[string]struct{} 561 } 562 563 //get返回存储节点 564 func (db *readTraceDB) Get(k []byte) ([]byte, error) { 565 if db.reads == nil { 566 db.reads = make(map[string]struct{}) 567 } 568 db.reads[string(k)] = struct{}{} 569 return db.db.Get(k) 570 } 571 572 //如果节点集包含给定的键,则返回true 573 func (db *readTraceDB) Has(key []byte) (bool, error) { 574 _, err := db.Get(key) 575 return err == nil, nil 576 } 577