@@ -36,30 +36,33 @@ import (
36
36
"github.com/ethereum/go-ethereum/eth/gasprice"
37
37
"github.com/ethereum/go-ethereum/event"
38
38
"github.com/ethereum/go-ethereum/internal/ethapi"
39
+ "github.com/ethereum/go-ethereum/les/vflux"
39
40
vfc "github.com/ethereum/go-ethereum/les/vflux/client"
40
41
"github.com/ethereum/go-ethereum/light"
41
42
"github.com/ethereum/go-ethereum/log"
42
43
"github.com/ethereum/go-ethereum/node"
43
44
"github.com/ethereum/go-ethereum/p2p"
44
45
"github.com/ethereum/go-ethereum/p2p/enode"
46
+ "github.com/ethereum/go-ethereum/p2p/enr"
45
47
"github.com/ethereum/go-ethereum/params"
48
+ "github.com/ethereum/go-ethereum/rlp"
46
49
"github.com/ethereum/go-ethereum/rpc"
47
50
)
48
51
49
52
type LightEthereum struct {
50
53
lesCommons
51
54
52
- peers * serverPeerSet
53
- reqDist * requestDistributor
54
- retriever * retrieveManager
55
- odr * LesOdr
56
- relay * lesTxRelay
57
- handler * clientHandler
58
- txPool * light.TxPool
59
- blockchain * light.LightChain
60
- serverPool * vfc.ServerPool
61
- dialCandidates enode.Iterator
62
- pruner * pruner
55
+ peers * serverPeerSet
56
+ reqDist * requestDistributor
57
+ retriever * retrieveManager
58
+ odr * LesOdr
59
+ relay * lesTxRelay
60
+ handler * clientHandler
61
+ txPool * light.TxPool
62
+ blockchain * light.LightChain
63
+ serverPool * vfc.ServerPool
64
+ serverPoolIterator enode.Iterator
65
+ pruner * pruner
63
66
64
67
bloomRequests chan chan * bloombits.Retrieval // Channel receiving bloom data retrieval requests
65
68
bloomIndexer * core.ChainIndexer // Bloom indexer operating during block imports
@@ -112,7 +115,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*LightEthereum, error) {
112
115
p2pConfig : & stack .Config ().P2P ,
113
116
}
114
117
115
- leth .serverPool , leth .dialCandidates = vfc .NewServerPool (lesDb , []byte ("serverpool:" ), time .Second , nil , & mclock.System {}, config .UltraLightServers , requestList )
118
+ leth .serverPool , leth .serverPoolIterator = vfc .NewServerPool (lesDb , []byte ("serverpool:" ), time .Second , leth . prenegQuery , & mclock.System {}, config .UltraLightServers , requestList )
116
119
leth .serverPool .AddMetrics (suggestedTimeoutGauge , totalValueGauge , serverSelectableGauge , serverConnectedGauge , sessionValueMeter , serverDialedMeter )
117
120
118
121
leth .retriever = newRetrieveManager (peers , leth .reqDist , leth .serverPool .GetTimeout )
@@ -189,6 +192,62 @@ func New(stack *node.Node, config *ethconfig.Config) (*LightEthereum, error) {
189
192
return leth , nil
190
193
}
191
194
195
+ // VfluxRequest sends a batch of requests to the given node through discv5 UDP TalkRequest and returns the responses
196
+ func (s * LightEthereum ) VfluxRequest (n * enode.Node , reqs vflux.Requests ) vflux.Replies {
197
+ reqsEnc , _ := rlp .EncodeToBytes (& reqs )
198
+ repliesEnc , _ := s .p2pServer .DiscV5 .TalkRequest (s .serverPool .DialNode (n ), "vfx" , reqsEnc )
199
+ var replies vflux.Replies
200
+ if len (repliesEnc ) == 0 || rlp .DecodeBytes (repliesEnc , & replies ) != nil {
201
+ return nil
202
+ }
203
+ return replies
204
+ }
205
+
206
+ // vfxVersion returns the version number of the "les" service subdomain of the vflux UDP
207
+ // service, as advertised in the ENR record
208
+ func (s * LightEthereum ) vfxVersion (n * enode.Node ) uint {
209
+ if n .Seq () == 0 {
210
+ var err error
211
+ if n , err = s .p2pServer .DiscV5 .RequestENR (n ); n != nil && err == nil && n .Seq () != 0 {
212
+ s .serverPool .Persist (n )
213
+ } else {
214
+ return 0
215
+ }
216
+ }
217
+
218
+ var les []rlp.RawValue
219
+ if err := n .Load (enr .WithEntry ("les" , & les )); err != nil || len (les ) < 1 {
220
+ return 0
221
+ }
222
+ var version uint
223
+ rlp .DecodeBytes (les [0 ], & version ) // Ignore additional fields (for forward compatibility).
224
+ return version
225
+ }
226
+
227
+ // prenegQuery sends a capacity query to the given server node to determine whether
228
+ // a connection slot is immediately available
229
+ func (s * LightEthereum ) prenegQuery (n * enode.Node ) int {
230
+ if s .vfxVersion (n ) < 1 {
231
+ // UDP query not supported, always try TCP connection
232
+ return 1
233
+ }
234
+
235
+ var requests vflux.Requests
236
+ requests .Add ("les" , vflux .CapacityQueryName , vflux.CapacityQueryReq {
237
+ Bias : 180 ,
238
+ AddTokens : []vflux.IntOrInf {{}},
239
+ })
240
+ replies := s .VfluxRequest (n , requests )
241
+ var cqr vflux.CapacityQueryReply
242
+ if replies .Get (0 , & cqr ) != nil || len (cqr ) != 1 { // Note: Get returns an error if replies is nil
243
+ return - 1
244
+ }
245
+ if cqr [0 ] > 0 {
246
+ return 1
247
+ }
248
+ return 0
249
+ }
250
+
192
251
type LightDummyAPI struct {}
193
252
194
253
// Etherbase is the address that mining rewards will be send to
@@ -269,7 +328,7 @@ func (s *LightEthereum) Protocols() []p2p.Protocol {
269
328
return p .Info ()
270
329
}
271
330
return nil
272
- }, s .dialCandidates )
331
+ }, s .serverPoolIterator )
273
332
}
274
333
275
334
// Start implements node.Lifecycle, starting all internal goroutines needed by the
0 commit comments