Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
whqwjb
go-ethereum
提交
c15d76a4
G
go-ethereum
项目概览
whqwjb
/
go-ethereum
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
G
go-ethereum
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
c15d76a4
编写于
12月 28, 2017
作者:
P
Péter Szilágyi
提交者:
Felix Lange
12月 28, 2017
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
p2p/discv5: fix reg lookup, polish code, use logger (#15737)
上级
5369a5c5
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
139 addition
and
142 deletion
+139
-142
p2p/discv5/net.go
p2p/discv5/net.go
+24
-32
p2p/discv5/node.go
p2p/discv5/node.go
+5
-0
p2p/discv5/ticket.go
p2p/discv5/ticket.go
+108
-109
p2p/discv5/topic.go
p2p/discv5/topic.go
+2
-1
未找到文件。
p2p/discv5/net.go
浏览文件 @
c15d76a4
...
...
@@ -51,16 +51,9 @@ const (
const
testTopic
=
"foo"
const
(
printDebugLogs
=
false
printTestImgLogs
=
false
)
func
debugLog
(
s
string
)
{
if
printDebugLogs
{
fmt
.
Println
(
s
)
}
}
// Network manages the table and all protocol interaction.
type
Network
struct
{
db
*
nodeDB
// database of known nodes
...
...
@@ -388,14 +381,14 @@ func (net *Network) loop() {
}
}()
resetNextTicket
:=
func
()
{
t
,
timeout
:=
net
.
ticketStore
.
nextFilteredTicket
()
if
t
!=
nextT
icket
{
nextTicket
=
t
t
icket
,
timeout
:=
net
.
ticketStore
.
nextFilteredTicket
()
if
nextTicket
!=
t
icket
{
nextTicket
=
t
icket
if
nextRegisterTimer
!=
nil
{
nextRegisterTimer
.
Stop
()
nextRegisterTime
=
nil
}
if
t
!=
nil
{
if
t
icket
!=
nil
{
nextRegisterTimer
=
time
.
NewTimer
(
timeout
)
nextRegisterTime
=
nextRegisterTimer
.
C
}
...
...
@@ -423,13 +416,13 @@ loop:
select
{
case
<-
net
.
closeReq
:
debugLog
(
"<-net.closeReq"
)
log
.
Trace
(
"<-net.closeReq"
)
break
loop
// Ingress packet handling.
case
pkt
:=
<-
net
.
read
:
//fmt.Println("read", pkt.ev)
debugLog
(
"<-net.read"
)
log
.
Trace
(
"<-net.read"
)
n
:=
net
.
internNode
(
&
pkt
)
prestate
:=
n
.
state
status
:=
"ok"
...
...
@@ -444,7 +437,7 @@ loop:
// State transition timeouts.
case
timeout
:=
<-
net
.
timeout
:
debugLog
(
"<-net.timeout"
)
log
.
Trace
(
"<-net.timeout"
)
if
net
.
timeoutTimers
[
timeout
]
==
nil
{
// Stale timer (was aborted).
continue
...
...
@@ -462,20 +455,20 @@ loop:
// Querying.
case
q
:=
<-
net
.
queryReq
:
debugLog
(
"<-net.queryReq"
)
log
.
Trace
(
"<-net.queryReq"
)
if
!
q
.
start
(
net
)
{
q
.
remote
.
deferQuery
(
q
)
}
// Interacting with the table.
case
f
:=
<-
net
.
tableOpReq
:
debugLog
(
"<-net.tableOpReq"
)
log
.
Trace
(
"<-net.tableOpReq"
)
f
()
net
.
tableOpResp
<-
struct
{}{}
// Topic registration stuff.
case
req
:=
<-
net
.
topicRegisterReq
:
debugLog
(
"<-net.topicRegisterReq"
)
log
.
Trace
(
"<-net.topicRegisterReq"
)
if
!
req
.
add
{
net
.
ticketStore
.
removeRegisterTopic
(
req
.
topic
)
continue
...
...
@@ -486,7 +479,7 @@ loop:
// determination for new topics.
// if topicRegisterLookupDone == nil {
if
topicRegisterLookupTarget
.
target
==
(
common
.
Hash
{})
{
debugLog
(
"topicRegisterLookupTarget == null"
)
log
.
Trace
(
"topicRegisterLookupTarget == null"
)
if
topicRegisterLookupTick
.
Stop
()
{
<-
topicRegisterLookupTick
.
C
}
...
...
@@ -496,7 +489,7 @@ loop:
}
case
nodes
:=
<-
topicRegisterLookupDone
:
debugLog
(
"<-topicRegisterLookupDone"
)
log
.
Trace
(
"<-topicRegisterLookupDone"
)
net
.
ticketStore
.
registerLookupDone
(
topicRegisterLookupTarget
,
nodes
,
func
(
n
*
Node
)
[]
byte
{
net
.
ping
(
n
,
n
.
addr
())
return
n
.
pingEcho
...
...
@@ -507,7 +500,7 @@ loop:
topicRegisterLookupDone
=
nil
case
<-
topicRegisterLookupTick
.
C
:
debugLog
(
"<-topicRegisterLookupTick"
)
log
.
Trace
(
"<-topicRegisterLookupTick"
)
if
(
topicRegisterLookupTarget
.
target
==
common
.
Hash
{})
{
target
,
delay
:=
net
.
ticketStore
.
nextRegisterLookup
()
topicRegisterLookupTarget
=
target
...
...
@@ -520,14 +513,14 @@ loop:
}
case
<-
nextRegisterTime
:
debugLog
(
"<-nextRegisterTime"
)
log
.
Trace
(
"<-nextRegisterTime"
)
net
.
ticketStore
.
ticketRegistered
(
*
nextTicket
)
//fmt.Println("sendTopicRegister", nextTicket.t.node.addr().String(), nextTicket.t.topics, nextTicket.idx, nextTicket.t.pong)
net
.
conn
.
sendTopicRegister
(
nextTicket
.
t
.
node
,
nextTicket
.
t
.
topics
,
nextTicket
.
idx
,
nextTicket
.
t
.
pong
)
case
req
:=
<-
net
.
topicSearchReq
:
if
refreshDone
==
nil
{
debugLog
(
"<-net.topicSearchReq"
)
log
.
Trace
(
"<-net.topicSearchReq"
)
info
,
ok
:=
searchInfo
[
req
.
topic
]
if
ok
{
if
req
.
delay
==
time
.
Duration
(
0
)
{
...
...
@@ -588,7 +581,7 @@ loop:
})
case
<-
statsDump
.
C
:
debugLog
(
"<-statsDump.C"
)
log
.
Trace
(
"<-statsDump.C"
)
/*r, ok := net.ticketStore.radius[testTopic]
if !ok {
fmt.Printf("(%x) no radius @ %v\n", net.tab.self.ID[:8], time.Now())
...
...
@@ -617,7 +610,7 @@ loop:
// Periodic / lookup-initiated bucket refresh.
case
<-
refreshTimer
.
C
:
debugLog
(
"<-refreshTimer.C"
)
log
.
Trace
(
"<-refreshTimer.C"
)
// TODO: ideally we would start the refresh timer after
// fallback nodes have been set for the first time.
if
refreshDone
==
nil
{
...
...
@@ -631,7 +624,7 @@ loop:
bucketRefreshTimer
.
Reset
(
bucketRefreshInterval
)
}()
case
newNursery
:=
<-
net
.
refreshReq
:
debugLog
(
"<-net.refreshReq"
)
log
.
Trace
(
"<-net.refreshReq"
)
if
newNursery
!=
nil
{
net
.
nursery
=
newNursery
}
...
...
@@ -641,7 +634,7 @@ loop:
}
net
.
refreshResp
<-
refreshDone
case
<-
refreshDone
:
debugLog
(
"<-net.refreshDone"
)
log
.
Trace
(
"<-net.refreshDone"
)
refreshDone
=
nil
list
:=
searchReqWhenRefreshDone
searchReqWhenRefreshDone
=
nil
...
...
@@ -652,7 +645,7 @@ loop:
}()
}
}
debugLog
(
"loop stopped"
)
log
.
Trace
(
"loop stopped"
)
log
.
Debug
(
fmt
.
Sprintf
(
"shutting down"
))
if
net
.
conn
!=
nil
{
...
...
@@ -1109,14 +1102,14 @@ func (net *Network) ping(n *Node, addr *net.UDPAddr) {
//fmt.Println(" not sent")
return
}
debugLog
(
fmt
.
Sprintf
(
"ping(node = %x)"
,
n
.
ID
[
:
8
])
)
log
.
Trace
(
"Pinging remote node"
,
"node"
,
n
.
ID
)
n
.
pingTopics
=
net
.
ticketStore
.
regTopicSet
()
n
.
pingEcho
=
net
.
conn
.
sendPing
(
n
,
addr
,
n
.
pingTopics
)
net
.
timedEvent
(
respTimeout
,
n
,
pongTimeout
)
}
func
(
net
*
Network
)
handlePing
(
n
*
Node
,
pkt
*
ingressPacket
)
{
debugLog
(
fmt
.
Sprintf
(
"handlePing(node = %x)"
,
n
.
ID
[
:
8
])
)
log
.
Trace
(
"Handling remote ping"
,
"node"
,
n
.
ID
)
ping
:=
pkt
.
data
.
(
*
ping
)
n
.
TCP
=
ping
.
From
.
TCP
t
:=
net
.
topictab
.
getTicket
(
n
,
ping
.
Topics
)
...
...
@@ -1131,7 +1124,7 @@ func (net *Network) handlePing(n *Node, pkt *ingressPacket) {
}
func
(
net
*
Network
)
handleKnownPong
(
n
*
Node
,
pkt
*
ingressPacket
)
error
{
debugLog
(
fmt
.
Sprintf
(
"handleKnownPong(node = %x)"
,
n
.
ID
[
:
8
])
)
log
.
Trace
(
"Handling known pong"
,
"node"
,
n
.
ID
)
net
.
abortTimedEvent
(
n
,
pongTimeout
)
now
:=
mclock
.
Now
()
ticket
,
err
:=
pongToTicket
(
now
,
n
.
pingTopics
,
n
,
pkt
)
...
...
@@ -1139,9 +1132,8 @@ func (net *Network) handleKnownPong(n *Node, pkt *ingressPacket) error {
// fmt.Printf("(%x) ticket: %+v\n", net.tab.self.ID[:8], pkt.data)
net
.
ticketStore
.
addTicket
(
now
,
pkt
.
data
.
(
*
pong
)
.
ReplyTok
,
ticket
)
}
else
{
debugLog
(
fmt
.
Sprintf
(
" error: %v"
,
err
)
)
log
.
Trace
(
"Failed to convert pong to ticket"
,
"err"
,
err
)
}
n
.
pingEcho
=
nil
n
.
pingTopics
=
nil
return
err
...
...
p2p/discv5/node.go
浏览文件 @
c15d76a4
...
...
@@ -273,6 +273,11 @@ func (n NodeID) GoString() string {
return
fmt
.
Sprintf
(
"discover.HexID(
\"
%x
\"
)"
,
n
[
:
])
}
// TerminalString returns a shortened hex string for terminal logging.
func
(
n
NodeID
)
TerminalString
()
string
{
return
hex
.
EncodeToString
(
n
[
:
8
])
}
// HexID converts a hex string to a NodeID.
// The string may be prefixed with 0x.
func
HexID
(
in
string
)
(
NodeID
,
error
)
{
...
...
p2p/discv5/ticket.go
浏览文件 @
c15d76a4
...
...
@@ -28,6 +28,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/mclock"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
)
const
(
...
...
@@ -128,8 +129,11 @@ type ticketStore struct {
// Contains buckets (for each absolute minute) of tickets
// that can be used in that minute.
// This is only set if the topic is being registered.
tickets
map
[
Topic
]
topicTickets
regtopics
[]
Topic
tickets
map
[
Topic
]
*
topicTickets
regQueue
[]
Topic
// Topic registration queue for round robin attempts
regSet
map
[
Topic
]
struct
{}
// Topic registration queue contents for fast filling
nodes
map
[
*
Node
]
*
ticket
nodeLastReq
map
[
*
Node
]
reqInfo
...
...
@@ -152,14 +156,16 @@ type sentQuery struct {
}
type
topicTickets
struct
{
buckets
map
[
timeBucket
][]
ticketRef
nextLookup
,
nextReg
mclock
.
AbsTime
buckets
map
[
timeBucket
][]
ticketRef
nextLookup
mclock
.
AbsTime
nextReg
mclock
.
AbsTime
}
func
newTicketStore
()
*
ticketStore
{
return
&
ticketStore
{
radius
:
make
(
map
[
Topic
]
*
topicRadius
),
tickets
:
make
(
map
[
Topic
]
topicTickets
),
tickets
:
make
(
map
[
Topic
]
*
topicTickets
),
regSet
:
make
(
map
[
Topic
]
struct
{}),
nodes
:
make
(
map
[
*
Node
]
*
ticket
),
nodeLastReq
:
make
(
map
[
*
Node
]
reqInfo
),
searchTopicMap
:
make
(
map
[
Topic
]
searchTopic
),
...
...
@@ -169,13 +175,13 @@ func newTicketStore() *ticketStore {
// addTopic starts tracking a topic. If register is true,
// the local node will register the topic and tickets will be collected.
func
(
s
*
ticketStore
)
addTopic
(
t
Topic
,
register
bool
)
{
debugLog
(
fmt
.
Sprintf
(
" addTopic(%v, %v)"
,
t
,
register
)
)
if
s
.
radius
[
t
]
==
nil
{
s
.
radius
[
t
]
=
newTopicRadius
(
t
)
func
(
s
*
ticketStore
)
addTopic
(
t
opic
Topic
,
register
bool
)
{
log
.
Trace
(
"Adding discovery topic"
,
"topic"
,
topic
,
"register"
,
register
)
if
s
.
radius
[
t
opic
]
==
nil
{
s
.
radius
[
t
opic
]
=
newTopicRadius
(
topic
)
}
if
register
&&
s
.
tickets
[
t
]
.
buckets
==
nil
{
s
.
tickets
[
t
]
=
topicTickets
{
buckets
:
make
(
map
[
timeBucket
][]
ticketRef
)}
if
register
&&
s
.
tickets
[
t
opic
]
==
nil
{
s
.
tickets
[
t
opic
]
=
&
topicTickets
{
buckets
:
make
(
map
[
timeBucket
][]
ticketRef
)}
}
}
...
...
@@ -194,7 +200,11 @@ func (s *ticketStore) removeSearchTopic(t Topic) {
// removeRegisterTopic deletes all tickets for the given topic.
func
(
s
*
ticketStore
)
removeRegisterTopic
(
topic
Topic
)
{
debugLog
(
fmt
.
Sprintf
(
" removeRegisterTopic(%v)"
,
topic
))
log
.
Trace
(
"Removing discovery topic"
,
"topic"
,
topic
)
if
s
.
tickets
[
topic
]
==
nil
{
log
.
Warn
(
"Removing non-existent discovery topic"
,
"topic"
,
topic
)
return
}
for
_
,
list
:=
range
s
.
tickets
[
topic
]
.
buckets
{
for
_
,
ref
:=
range
list
{
ref
.
t
.
refCnt
--
...
...
@@ -216,23 +226,35 @@ func (s *ticketStore) regTopicSet() []Topic {
}
// nextRegisterLookup returns the target of the next lookup for ticket collection.
func
(
s
*
ticketStore
)
nextRegisterLookup
()
(
lookup
lookupInfo
,
delay
time
.
Duration
)
{
debugLog
(
"nextRegisterLookup()"
)
firstTopic
,
ok
:=
s
.
iterRegTopics
()
for
topic
:=
firstTopic
;
ok
;
{
debugLog
(
fmt
.
Sprintf
(
" checking topic %v, len(s.tickets[topic]) = %d"
,
topic
,
len
(
s
.
tickets
[
topic
]
.
buckets
)))
if
s
.
tickets
[
topic
]
.
buckets
!=
nil
&&
s
.
needMoreTickets
(
topic
)
{
next
:=
s
.
radius
[
topic
]
.
nextTarget
(
false
)
debugLog
(
fmt
.
Sprintf
(
" %x 1s"
,
next
.
target
[
:
8
]))
return
next
,
100
*
time
.
Millisecond
func
(
s
*
ticketStore
)
nextRegisterLookup
()
(
lookupInfo
,
time
.
Duration
)
{
// Queue up any new topics (or discarded ones), preserving iteration order
for
topic
:=
range
s
.
tickets
{
if
_
,
ok
:=
s
.
regSet
[
topic
];
!
ok
{
s
.
regQueue
=
append
(
s
.
regQueue
,
topic
)
s
.
regSet
[
topic
]
=
struct
{}{}
}
topic
,
ok
=
s
.
iterRegTopics
()
if
topic
==
firstTopic
{
break
// We have checked all topics.
}
// Iterate over the set of all topics and look up the next suitable one
for
len
(
s
.
regQueue
)
>
0
{
// Fetch the next topic from the queue, and ensure it still exists
topic
:=
s
.
regQueue
[
0
]
s
.
regQueue
=
s
.
regQueue
[
1
:
]
delete
(
s
.
regSet
,
topic
)
if
s
.
tickets
[
topic
]
==
nil
{
continue
}
// If the topic needs more tickets, return it
if
s
.
tickets
[
topic
]
.
nextLookup
<
mclock
.
Now
()
{
next
,
delay
:=
s
.
radius
[
topic
]
.
nextTarget
(
false
),
100
*
time
.
Millisecond
log
.
Trace
(
"Found discovery topic to register"
,
"topic"
,
topic
,
"target"
,
next
.
target
,
"delay"
,
delay
)
return
next
,
delay
}
}
debugLog
(
" null, 40s"
)
return
lookupInfo
{},
40
*
time
.
Second
// No registration topics found or all exhausted, sleep
delay
:=
40
*
time
.
Second
log
.
Trace
(
"No topic found to register"
,
"delay"
,
delay
)
return
lookupInfo
{},
delay
}
func
(
s
*
ticketStore
)
nextSearchLookup
(
topic
Topic
)
lookupInfo
{
...
...
@@ -246,40 +268,22 @@ func (s *ticketStore) nextSearchLookup(topic Topic) lookupInfo {
return
target
}
// iterRegTopics returns topics to register in arbitrary order.
// The second return value is false if there are no topics.
func
(
s
*
ticketStore
)
iterRegTopics
()
(
Topic
,
bool
)
{
debugLog
(
"iterRegTopics()"
)
if
len
(
s
.
regtopics
)
==
0
{
if
len
(
s
.
tickets
)
==
0
{
debugLog
(
" false"
)
return
""
,
false
}
// Refill register list.
for
t
:=
range
s
.
tickets
{
s
.
regtopics
=
append
(
s
.
regtopics
,
t
)
}
// ticketsInWindow returns the tickets of a given topic in the registration window.
func
(
s
*
ticketStore
)
ticketsInWindow
(
topic
Topic
)
[]
ticketRef
{
// Sanity check that the topic still exists before operating on it
if
s
.
tickets
[
topic
]
==
nil
{
log
.
Warn
(
"Listing non-existing discovery tickets"
,
"topic"
,
topic
)
return
nil
}
topic
:=
s
.
regtopics
[
len
(
s
.
regtopics
)
-
1
]
s
.
regtopics
=
s
.
regtopics
[
:
len
(
s
.
regtopics
)
-
1
]
debugLog
(
" "
+
string
(
topic
)
+
" true"
)
return
topic
,
true
}
func
(
s
*
ticketStore
)
needMoreTickets
(
t
Topic
)
bool
{
return
s
.
tickets
[
t
]
.
nextLookup
<
mclock
.
Now
()
}
// Gather all the tickers in the next time window
var
tickets
[]
ticketRef
// ticketsInWindow returns the tickets of a given topic in the registration window.
func
(
s
*
ticketStore
)
ticketsInWindow
(
t
Topic
)
[]
ticketRef
{
ltBucket
:=
s
.
lastBucketFetched
var
res
[]
ticketRef
tickets
:=
s
.
tickets
[
t
]
.
buckets
for
g
:=
ltBucket
;
g
<
ltBucket
+
timeWindow
;
g
++
{
res
=
append
(
res
,
tickets
[
g
]
...
)
buckets
:=
s
.
tickets
[
topic
]
.
buckets
for
idx
:=
timeBucket
(
0
);
idx
<
timeWindow
;
idx
++
{
tickets
=
append
(
tickets
,
buckets
[
s
.
lastBucketFetched
+
idx
]
...
)
}
debugLog
(
fmt
.
Sprintf
(
"ticketsInWindow(%v) = %v"
,
t
,
len
(
res
)
))
return
re
s
log
.
Trace
(
"Retrieved discovery registration tickets"
,
"topic"
,
topic
,
"from"
,
s
.
lastBucketFetched
,
"tickets"
,
len
(
tickets
))
return
ticket
s
}
func
(
s
*
ticketStore
)
removeExcessTickets
(
t
Topic
)
{
...
...
@@ -317,53 +321,55 @@ func (s ticketRefByWaitTime) Swap(i, j int) {
func
(
s
*
ticketStore
)
addTicketRef
(
r
ticketRef
)
{
topic
:=
r
.
t
.
topics
[
r
.
idx
]
t
:=
s
.
tickets
[
topic
]
if
t
.
buckets
==
nil
{
tickets
:=
s
.
tickets
[
topic
]
if
tickets
==
nil
{
log
.
Warn
(
"Adding ticket to non-existent topic"
,
"topic"
,
topic
)
return
}
bucket
:=
timeBucket
(
r
.
t
.
regTime
[
r
.
idx
]
/
mclock
.
AbsTime
(
ticketTimeBucketLen
))
t
.
buckets
[
bucket
]
=
append
(
t
.
buckets
[
bucket
],
r
)
t
ickets
.
buckets
[
bucket
]
=
append
(
tickets
.
buckets
[
bucket
],
r
)
r
.
t
.
refCnt
++
min
:=
mclock
.
Now
()
-
mclock
.
AbsTime
(
collectFrequency
)
*
maxCollectDebt
if
t
.
nextLookup
<
min
{
t
.
nextLookup
=
min
if
t
ickets
.
nextLookup
<
min
{
t
ickets
.
nextLookup
=
min
}
t
.
nextLookup
+=
mclock
.
AbsTime
(
collectFrequency
)
s
.
tickets
[
topic
]
=
t
tickets
.
nextLookup
+=
mclock
.
AbsTime
(
collectFrequency
)
//s.removeExcessTickets(topic)
}
func
(
s
*
ticketStore
)
nextFilteredTicket
()
(
t
*
ticketRef
,
wait
time
.
Duration
)
{
func
(
s
*
ticketStore
)
nextFilteredTicket
()
(
*
ticketRef
,
time
.
Duration
)
{
now
:=
mclock
.
Now
()
for
{
t
,
wait
=
s
.
nextRegisterableTicket
()
if
t
==
nil
{
return
t
icket
,
wait
:
=
s
.
nextRegisterableTicket
()
if
t
icket
==
nil
{
return
ticket
,
wait
}
log
.
Trace
(
"Found discovery ticket to register"
,
"node"
,
ticket
.
t
.
node
,
"serial"
,
ticket
.
t
.
serial
,
"wait"
,
wait
)
regTime
:=
now
+
mclock
.
AbsTime
(
wait
)
topic
:=
t
.
t
.
topics
[
t
.
idx
]
topic
:=
t
icket
.
t
.
topics
[
ticke
t
.
idx
]
if
regTime
>=
s
.
tickets
[
topic
]
.
nextReg
{
return
return
ticket
,
wait
}
s
.
removeTicketRef
(
*
t
)
s
.
removeTicketRef
(
*
t
icket
)
}
}
func
(
s
*
ticketStore
)
ticketRegistered
(
t
ticketRef
)
{
func
(
s
*
ticketStore
)
ticketRegistered
(
ref
ticketRef
)
{
now
:=
mclock
.
Now
()
topic
:=
t
.
t
.
topics
[
t
.
idx
]
t
t
:=
s
.
tickets
[
topic
]
topic
:=
ref
.
t
.
topics
[
ref
.
idx
]
t
ickets
:=
s
.
tickets
[
topic
]
min
:=
now
-
mclock
.
AbsTime
(
registerFrequency
)
*
maxRegisterDebt
if
min
>
t
t
.
nextReg
{
t
t
.
nextReg
=
min
if
min
>
t
ickets
.
nextReg
{
t
ickets
.
nextReg
=
min
}
t
t
.
nextReg
+=
mclock
.
AbsTime
(
registerFrequency
)
s
.
tickets
[
topic
]
=
t
t
t
ickets
.
nextReg
+=
mclock
.
AbsTime
(
registerFrequency
)
s
.
tickets
[
topic
]
=
t
ickets
s
.
removeTicketRef
(
t
)
s
.
removeTicketRef
(
ref
)
}
// nextRegisterableTicket returns the next ticket that can be used
...
...
@@ -374,16 +380,7 @@ func (s *ticketStore) ticketRegistered(t ticketRef) {
//
// A ticket can be returned more than once with <= zero wait time in case
// the ticket contains multiple topics.
func
(
s
*
ticketStore
)
nextRegisterableTicket
()
(
t
*
ticketRef
,
wait
time
.
Duration
)
{
defer
func
()
{
if
t
==
nil
{
debugLog
(
" nil"
)
}
else
{
debugLog
(
fmt
.
Sprintf
(
" node = %x sn = %v wait = %v"
,
t
.
t
.
node
.
ID
[
:
8
],
t
.
t
.
serial
,
wait
))
}
}()
debugLog
(
"nextRegisterableTicket()"
)
func
(
s
*
ticketStore
)
nextRegisterableTicket
()
(
*
ticketRef
,
time
.
Duration
)
{
now
:=
mclock
.
Now
()
if
s
.
nextTicketCached
!=
nil
{
return
s
.
nextTicketCached
,
time
.
Duration
(
s
.
nextTicketCached
.
topicRegTime
()
-
now
)
...
...
@@ -412,9 +409,8 @@ func (s *ticketStore) nextRegisterableTicket() (t *ticketRef, wait time.Duration
return
nil
,
0
}
if
nextTicket
.
t
!=
nil
{
wait
=
time
.
Duration
(
nextTicket
.
topicRegTime
()
-
now
)
s
.
nextTicketCached
=
&
nextTicket
return
&
nextTicket
,
wait
return
&
nextTicket
,
time
.
Duration
(
nextTicket
.
topicRegTime
()
-
now
)
}
s
.
lastBucketFetched
=
bucket
}
...
...
@@ -422,14 +418,17 @@ func (s *ticketStore) nextRegisterableTicket() (t *ticketRef, wait time.Duration
// removeTicket removes a ticket from the ticket store
func
(
s
*
ticketStore
)
removeTicketRef
(
ref
ticketRef
)
{
debugLog
(
fmt
.
Sprintf
(
"removeTicketRef(node = %x sn = %v)"
,
ref
.
t
.
node
.
ID
[
:
8
],
ref
.
t
.
serial
))
log
.
Trace
(
"Removing discovery ticket reference"
,
"node"
,
ref
.
t
.
node
.
ID
,
"serial"
,
ref
.
t
.
serial
)
topic
:=
ref
.
topic
()
tickets
:=
s
.
tickets
[
topic
]
.
buckets
tickets
:=
s
.
tickets
[
topic
]
if
tickets
==
nil
{
log
.
Warn
(
"Removing tickets from unknown topic"
,
"topic"
,
topic
)
return
}
bucket
:=
timeBucket
(
ref
.
t
.
regTime
[
ref
.
idx
]
/
mclock
.
AbsTime
(
ticketTimeBucketLen
))
list
:=
tickets
[
bucket
]
list
:=
tickets
.
buckets
[
bucket
]
idx
:=
-
1
for
i
,
bt
:=
range
list
{
if
bt
.
t
==
ref
.
t
{
...
...
@@ -442,9 +441,9 @@ func (s *ticketStore) removeTicketRef(ref ticketRef) {
}
list
=
append
(
list
[
:
idx
],
list
[
idx
+
1
:
]
...
)
if
len
(
list
)
!=
0
{
tickets
[
bucket
]
=
list
tickets
.
buckets
[
bucket
]
=
list
}
else
{
delete
(
tickets
,
bucket
)
delete
(
tickets
.
buckets
,
bucket
)
}
ref
.
t
.
refCnt
--
if
ref
.
t
.
refCnt
==
0
{
...
...
@@ -523,21 +522,21 @@ func (s *ticketStore) adjustWithTicket(now mclock.AbsTime, targetHash common.Has
}
}
func
(
s
*
ticketStore
)
addTicket
(
localTime
mclock
.
AbsTime
,
pingHash
[]
byte
,
t
*
ticket
)
{
debugLog
(
fmt
.
Sprintf
(
"add(node = %x sn = %v)"
,
t
.
node
.
ID
[
:
8
],
t
.
serial
)
)
func
(
s
*
ticketStore
)
addTicket
(
localTime
mclock
.
AbsTime
,
pingHash
[]
byte
,
t
icket
*
ticket
)
{
log
.
Trace
(
"Adding discovery ticket"
,
"node"
,
ticket
.
node
.
ID
,
"serial"
,
ticket
.
serial
)
lastReq
,
ok
:=
s
.
nodeLastReq
[
t
.
node
]
lastReq
,
ok
:=
s
.
nodeLastReq
[
t
icket
.
node
]
if
!
(
ok
&&
bytes
.
Equal
(
pingHash
,
lastReq
.
pingHash
))
{
return
}
s
.
adjustWithTicket
(
localTime
,
lastReq
.
lookup
.
target
,
t
)
s
.
adjustWithTicket
(
localTime
,
lastReq
.
lookup
.
target
,
t
icket
)
if
lastReq
.
lookup
.
radiusLookup
||
s
.
nodes
[
t
.
node
]
!=
nil
{
if
lastReq
.
lookup
.
radiusLookup
||
s
.
nodes
[
t
icket
.
node
]
!=
nil
{
return
}
topic
:=
lastReq
.
lookup
.
topic
topicIdx
:=
t
.
findIdx
(
topic
)
topicIdx
:=
t
icket
.
findIdx
(
topic
)
if
topicIdx
==
-
1
{
return
}
...
...
@@ -548,29 +547,29 @@ func (s *ticketStore) addTicket(localTime mclock.AbsTime, pingHash []byte, t *ti
}
if
_
,
ok
:=
s
.
tickets
[
topic
];
ok
{
wait
:=
t
.
regTime
[
topicIdx
]
-
localTime
wait
:=
t
icket
.
regTime
[
topicIdx
]
-
localTime
rnd
:=
rand
.
ExpFloat64
()
if
rnd
>
10
{
rnd
=
10
}
if
float64
(
wait
)
<
float64
(
keepTicketConst
)
+
float64
(
keepTicketExp
)
*
rnd
{
// use the ticket to register this topic
//fmt.Println("addTicket", t
.node.ID[:8], t.node.addr().String(), t.serial,
t.pong)
s
.
addTicketRef
(
ticketRef
{
t
,
topicIdx
})
//fmt.Println("addTicket", t
icket.node.ID[:8], ticket.node.addr().String(), ticket.serial, ticke
t.pong)
s
.
addTicketRef
(
ticketRef
{
t
icket
,
topicIdx
})
}
}
if
t
.
refCnt
>
0
{
if
t
icket
.
refCnt
>
0
{
s
.
nextTicketCached
=
nil
s
.
nodes
[
t
.
node
]
=
t
s
.
nodes
[
t
icket
.
node
]
=
ticke
t
}
}
func
(
s
*
ticketStore
)
getNodeTicket
(
node
*
Node
)
*
ticket
{
if
s
.
nodes
[
node
]
==
nil
{
debugLog
(
fmt
.
Sprintf
(
"getNodeTicket(%x) sn = nil"
,
node
.
ID
[
:
8
])
)
log
.
Trace
(
"Retrieving node ticket"
,
"node"
,
node
.
ID
,
"serial"
,
nil
)
}
else
{
debugLog
(
fmt
.
Sprintf
(
"getNodeTicket(%x) sn = %v"
,
node
.
ID
[
:
8
],
s
.
nodes
[
node
]
.
serial
)
)
log
.
Trace
(
"Retrieving node ticket"
,
"node"
,
node
.
ID
,
"serial"
,
s
.
nodes
[
node
]
.
serial
)
}
return
s
.
nodes
[
node
]
}
...
...
p2p/discv5/topic.go
浏览文件 @
c15d76a4
...
...
@@ -24,6 +24,7 @@ import (
"time"
"github.com/ethereum/go-ethereum/common/mclock"
"github.com/ethereum/go-ethereum/log"
)
const
(
...
...
@@ -235,7 +236,7 @@ func (t *topicTable) deleteEntry(e *topicEntry) {
// It is assumed that topics and waitPeriods have the same length.
func
(
t
*
topicTable
)
useTicket
(
node
*
Node
,
serialNo
uint32
,
topics
[]
Topic
,
idx
int
,
issueTime
uint64
,
waitPeriods
[]
uint32
)
(
registered
bool
)
{
debugLog
(
fmt
.
Sprintf
(
"useTicket %v %v %v"
,
serialNo
,
topics
,
waitPeriods
)
)
log
.
Trace
(
"Using discovery ticket"
,
"serial"
,
serialNo
,
"topics"
,
topics
,
"waits"
,
waitPeriods
)
//fmt.Println("useTicket", serialNo, topics, waitPeriods)
t
.
collectGarbage
()
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录