-
Notifications
You must be signed in to change notification settings - Fork 15
/
odr.go
176 lines (152 loc) · 5.25 KB
/
odr.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
// Copyright 2016 The github.com/blockchain-analysis-study/go-ethereum-analysis Authors
// This file is part of the github.com/blockchain-analysis-study/go-ethereum-analysis library.
//
// The github.com/blockchain-analysis-study/go-ethereum-analysis library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The github.com/blockchain-analysis-study/go-ethereum-analysis library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the github.com/blockchain-analysis-study/go-ethereum-analysis library. If not, see <http://www.gnu.org/licenses/>.
package les
import (
"context"
"github.com/blockchain-analysis-study/go-ethereum-analysis/core"
"github.com/blockchain-analysis-study/go-ethereum-analysis/ethdb"
"github.com/blockchain-analysis-study/go-ethereum-analysis/light"
"github.com/blockchain-analysis-study/go-ethereum-analysis/log"
)
// LesOdr implements light.OdrBackend
type LesOdr struct {
// 操作 odr 相关的db
db ethdb.Database
// 几个索引器的引用
chtIndexer, bloomTrieIndexer, bloomIndexer *core.ChainIndexer
// 请求拉取管理器
retriever *retrieveManager
// 关闭信号通道
stop chan struct{}
}
func NewLesOdr(db ethdb.Database, retriever *retrieveManager) *LesOdr {
return &LesOdr{
db: db,
retriever: retriever,
stop: make(chan struct{}),
}
}
// Stop cancels all pending retrievals
func (odr *LesOdr) Stop() {
close(odr.stop)
}
// Database returns the backing database
func (odr *LesOdr) Database() ethdb.Database {
return odr.db
}
// SetIndexers adds the necessary chain indexers to the ODR backend
//
// SetIndexers向ODR backend添加必要的链索引器
func (odr *LesOdr) SetIndexers(chtIndexer, bloomTrieIndexer, bloomIndexer *core.ChainIndexer) {
odr.chtIndexer = chtIndexer
odr.bloomTrieIndexer = bloomTrieIndexer
odr.bloomIndexer = bloomIndexer
}
// ChtIndexer returns the CHT chain indexer
func (odr *LesOdr) ChtIndexer() *core.ChainIndexer {
return odr.chtIndexer
}
// BloomTrieIndexer returns the bloom trie chain indexer
//
// BloomTrieIndexer: 返回Bloom Trie链索引器
func (odr *LesOdr) BloomTrieIndexer() *core.ChainIndexer {
return odr.bloomTrieIndexer
}
// BloomIndexer returns the bloombits chain indexer
//
// BloomIndexer: 返回Bloombits链索引器
func (odr *LesOdr) BloomIndexer() *core.ChainIndexer {
return odr.bloomIndexer
}
const (
MsgBlockBodies = iota
MsgCode
MsgReceipts
MsgProofsV1
MsgProofsV2
MsgHeaderProofs
MsgHelperTrieProofs
)
// Msg encodes a LES message that delivers reply data for a request
type Msg struct {
MsgType int
ReqID uint64
Obj interface{}
}
// Retrieve tries to fetch an object from the LES network.
// If the network retrieval was successful, it stores the object in local db.
//
/**
Retrieve: 尝试从LES网络中获取对象。 如果网络检索成功,它将对象存储在本地数据库中.
TODO 一般只有两个 Indexer 需要用到
todo 一) BloomTrieIndexer
todo 二) ChtIndexer
*/
func (odr *LesOdr) Retrieve(ctx context.Context, req light.OdrRequest) (err error) {
// 如果是BloomTrieIndexer的话, 那么 req是 `BloomRequest`
// 如果是ChtIndexer的话, 那么 req是 `ChtRequest`
// 类型强转处理
lreq := LesRequest(req)
// 随机生成一个reqId
reqID := genReqID()
// 构造对应的req体
rq := &distReq{
//
getCost: func(dp distPeer) uint64 {
return lreq.GetCost(dp.(*peer))
},
canSend: func(dp distPeer) bool {
p := dp.(*peer)
return lreq.CanSend(p)
},
// TODO 这个方法,最终会在 odr.loop() 中被调用
request: func(dp distPeer) func() {
p := dp.(*peer)
cost := lreq.GetCost(p)
// 调整下 server 端的资源
p.fcServer.QueueRequest(reqID, cost)
/**
TODO ChtRequest 和 BloomRequest 都会发起 拉取Header 的req
*/
return func() { lreq.Request(reqID, p) }
},
}
/**
todo 将构建好的 req 发起拉取, 并且对 proof 做校验
*/
if err = odr.retriever.retrieve(ctx, reqID, rq, func(p distPeer, msg *Msg) error { return lreq.Validate(odr.db, msg) }, odr.stop); err == nil {
// retrieved from network, store in db
//
// todo #####################################
// todo #####################################
// todo #####################################
// todo #####################################
// todo #####################################
// todo 极度重要
// todo
// todo 从网络检索,存储在数据库中
//
// todo #####################################
// todo #####################################
// todo #####################################
// todo #####################################
// todo #####################################
req.StoreResult(odr.db)
} else {
log.Debug("Failed to retrieve data from network", "err", err)
}
return
}