Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
Geth-Modification
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
张蕾
Geth-Modification
Commits
b40dc8a1
Commit
b40dc8a1
authored
9 years ago
by
Péter Szilágyi
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
eth/downloader: implement concurrent header downloads
parent
fe532a98
Changes
4
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
584 additions
and
211 deletions
+584
-211
downloader.go
eth/downloader/downloader.go
+299
-181
downloader_test.go
eth/downloader/downloader_test.go
+24
-23
peer.go
eth/downloader/peer.go
+61
-5
queue.go
eth/downloader/queue.go
+200
-2
No files found.
eth/downloader/downloader.go
View file @
b40dc8a1
This diff is collapsed.
Click to expand it.
eth/downloader/downloader_test.go
View file @
b40dc8a1
...
...
@@ -560,8 +560,8 @@ func (dl *downloadTester) peerGetAbsHeadersFn(id string, delay time.Duration) fu
hashes
:=
dl
.
peerHashes
[
id
]
headers
:=
dl
.
peerHeaders
[
id
]
result
:=
make
([]
*
types
.
Header
,
0
,
amount
)
for
i
:=
0
;
i
<
amount
&&
len
(
hashes
)
-
int
(
origin
)
-
1
-
i
>=
0
;
i
++
{
if
header
,
ok
:=
headers
[
hashes
[
len
(
hashes
)
-
int
(
origin
)
-
1
-
i
]];
ok
{
for
i
:=
0
;
i
<
amount
&&
len
(
hashes
)
-
int
(
origin
)
-
1
-
i
*
(
skip
+
1
)
>=
0
;
i
++
{
if
header
,
ok
:=
headers
[
hashes
[
len
(
hashes
)
-
int
(
origin
)
-
1
-
i
*
(
skip
+
1
)
]];
ok
{
result
=
append
(
result
,
header
)
}
}
...
...
@@ -1348,27 +1348,28 @@ func testBlockHeaderAttackerDropping(t *testing.T, protocol int) {
result
error
drop
bool
}{
{
nil
,
false
},
// Sync succeeded, all is well
{
errBusy
,
false
},
// Sync is already in progress, no problem
{
errUnknownPeer
,
false
},
// Peer is unknown, was already dropped, don't double drop
{
errBadPeer
,
true
},
// Peer was deemed bad for some reason, drop it
{
errStallingPeer
,
true
},
// Peer was detected to be stalling, drop it
{
errNoPeers
,
false
},
// No peers to download from, soft race, no issue
{
errTimeout
,
true
},
// No hashes received in due time, drop the peer
{
errEmptyHashSet
,
true
},
// No hashes were returned as a response, drop as it's a dead end
{
errEmptyHeaderSet
,
true
},
// No headers were returned as a response, drop as it's a dead end
{
errPeersUnavailable
,
true
},
// Nobody had the advertised blocks, drop the advertiser
{
errInvalidAncestor
,
true
},
// Agreed upon ancestor is not acceptable, drop the chain rewriter
{
errInvalidChain
,
true
},
// Hash chain was detected as invalid, definitely drop
{
errInvalidBlock
,
false
},
// A bad peer was detected, but not the sync origin
{
errInvalidBody
,
false
},
// A bad peer was detected, but not the sync origin
{
errInvalidReceipt
,
false
},
// A bad peer was detected, but not the sync origin
{
errCancelHashFetch
,
false
},
// Synchronisation was canceled, origin may be innocent, don't drop
{
errCancelBlockFetch
,
false
},
// Synchronisation was canceled, origin may be innocent, don't drop
{
errCancelHeaderFetch
,
false
},
// Synchronisation was canceled, origin may be innocent, don't drop
{
errCancelBodyFetch
,
false
},
// Synchronisation was canceled, origin may be innocent, don't drop
{
errCancelReceiptFetch
,
false
},
// Synchronisation was canceled, origin may be innocent, don't drop
{
errCancelProcessing
,
false
},
// Synchronisation was canceled, origin may be innocent, don't drop
{
nil
,
false
},
// Sync succeeded, all is well
{
errBusy
,
false
},
// Sync is already in progress, no problem
{
errUnknownPeer
,
false
},
// Peer is unknown, was already dropped, don't double drop
{
errBadPeer
,
true
},
// Peer was deemed bad for some reason, drop it
{
errStallingPeer
,
true
},
// Peer was detected to be stalling, drop it
{
errNoPeers
,
false
},
// No peers to download from, soft race, no issue
{
errTimeout
,
true
},
// No hashes received in due time, drop the peer
{
errEmptyHashSet
,
true
},
// No hashes were returned as a response, drop as it's a dead end
{
errEmptyHeaderSet
,
true
},
// No headers were returned as a response, drop as it's a dead end
{
errPeersUnavailable
,
true
},
// Nobody had the advertised blocks, drop the advertiser
{
errInvalidAncestor
,
true
},
// Agreed upon ancestor is not acceptable, drop the chain rewriter
{
errInvalidChain
,
true
},
// Hash chain was detected as invalid, definitely drop
{
errInvalidBlock
,
false
},
// A bad peer was detected, but not the sync origin
{
errInvalidBody
,
false
},
// A bad peer was detected, but not the sync origin
{
errInvalidReceipt
,
false
},
// A bad peer was detected, but not the sync origin
{
errCancelHashFetch
,
false
},
// Synchronisation was canceled, origin may be innocent, don't drop
{
errCancelBlockFetch
,
false
},
// Synchronisation was canceled, origin may be innocent, don't drop
{
errCancelHeaderFetch
,
false
},
// Synchronisation was canceled, origin may be innocent, don't drop
{
errCancelBodyFetch
,
false
},
// Synchronisation was canceled, origin may be innocent, don't drop
{
errCancelReceiptFetch
,
false
},
// Synchronisation was canceled, origin may be innocent, don't drop
{
errCancelHeaderProcessing
,
false
},
// Synchronisation was canceled, origin may be innocent, don't drop
{
errCancelContentProcessing
,
false
},
// Synchronisation was canceled, origin may be innocent, don't drop
}
// Run the tests and check disconnection status
tester
:=
newTester
()
...
...
This diff is collapsed.
Click to expand it.
eth/downloader/peer.go
View file @
b40dc8a1
...
...
@@ -58,15 +58,18 @@ type peer struct {
id
string
// Unique identifier of the peer
head
common
.
Hash
// Hash of the peers latest known block
headerIdle
int32
// Current header activity state of the peer (idle = 0, active = 1)
blockIdle
int32
// Current block activity state of the peer (idle = 0, active = 1)
receiptIdle
int32
// Current receipt activity state of the peer (idle = 0, active = 1)
stateIdle
int32
// Current node data activity state of the peer (idle = 0, active = 1)
headerThroughput
float64
// Number of headers measured to be retrievable per second
blockThroughput
float64
// Number of blocks (bodies) measured to be retrievable per second
receiptThroughput
float64
// Number of receipts measured to be retrievable per second
stateThroughput
float64
// Number of node data pieces measured to be retrievable per second
blockStarted
time
.
Time
// Time instance when the last block (body)fetch was started
headerStarted
time
.
Time
// Time instance when the last header fetch was started
blockStarted
time
.
Time
// Time instance when the last block (body) fetch was started
receiptStarted
time
.
Time
// Time instance when the last receipt fetch was started
stateStarted
time
.
Time
// Time instance when the last node data fetch was started
...
...
@@ -118,10 +121,12 @@ func (p *peer) Reset() {
p
.
lock
.
Lock
()
defer
p
.
lock
.
Unlock
()
atomic
.
StoreInt32
(
&
p
.
headerIdle
,
0
)
atomic
.
StoreInt32
(
&
p
.
blockIdle
,
0
)
atomic
.
StoreInt32
(
&
p
.
receiptIdle
,
0
)
atomic
.
StoreInt32
(
&
p
.
stateIdle
,
0
)
p
.
headerThroughput
=
0
p
.
blockThroughput
=
0
p
.
receiptThroughput
=
0
p
.
stateThroughput
=
0
...
...
@@ -151,6 +156,24 @@ func (p *peer) Fetch61(request *fetchRequest) error {
return
nil
}
// FetchHeaders sends a header retrieval request to the remote peer.
func
(
p
*
peer
)
FetchHeaders
(
from
uint64
,
count
int
)
error
{
// Sanity check the protocol version
if
p
.
version
<
62
{
panic
(
fmt
.
Sprintf
(
"header fetch [eth/62+] requested on eth/%d"
,
p
.
version
))
}
// Short circuit if the peer is already fetching
if
!
atomic
.
CompareAndSwapInt32
(
&
p
.
headerIdle
,
0
,
1
)
{
return
errAlreadyFetching
}
p
.
headerStarted
=
time
.
Now
()
// Issue the header retrieval request (absolut upwards without gaps)
go
p
.
getAbsHeaders
(
from
,
count
,
0
,
false
)
return
nil
}
// FetchBodies sends a block body retrieval request to the remote peer.
func
(
p
*
peer
)
FetchBodies
(
request
*
fetchRequest
)
error
{
// Sanity check the protocol version
...
...
@@ -217,6 +240,13 @@ func (p *peer) FetchNodeData(request *fetchRequest) error {
return
nil
}
// SetHeadersIdle sets the peer to idle, allowing it to execute new header retrieval
// requests. Its estimated header retrieval throughput is updated with that measured
// just now.
func
(
p
*
peer
)
SetHeadersIdle
(
delivered
int
)
{
p
.
setIdle
(
p
.
headerStarted
,
delivered
,
&
p
.
headerThroughput
,
&
p
.
headerIdle
)
}
// SetBlocksIdle sets the peer to idle, allowing it to execute new block retrieval
// requests. Its estimated block retrieval throughput is updated with that measured
// just now.
...
...
@@ -264,6 +294,15 @@ func (p *peer) setIdle(started time.Time, delivered int, throughput *float64, id
*
throughput
=
(
1
-
throughputImpact
)
*
(
*
throughput
)
+
throughputImpact
*
measured
}
// HeaderCapacity retrieves the peers header download allowance based on its
// previously discovered throughput.
func
(
p
*
peer
)
HeaderCapacity
()
int
{
p
.
lock
.
RLock
()
defer
p
.
lock
.
RUnlock
()
return
int
(
math
.
Max
(
1
,
math
.
Min
(
p
.
headerThroughput
*
float64
(
headerTargetRTT
)
/
float64
(
time
.
Second
),
float64
(
MaxHeaderFetch
))))
}
// BlockCapacity retrieves the peers block download allowance based on its
// previously discovered throughput.
func
(
p
*
peer
)
BlockCapacity
()
int
{
...
...
@@ -323,14 +362,15 @@ func (p *peer) String() string {
defer
p
.
lock
.
RUnlock
()
return
fmt
.
Sprintf
(
"Peer %s [%s]"
,
p
.
id
,
fmt
.
Sprintf
(
"blocks %3.2f/s, "
,
p
.
blockThroughput
)
+
fmt
.
Sprintf
(
"headers %3.2f/s, "
,
p
.
headerThroughput
)
+
fmt
.
Sprintf
(
"blocks %3.2f/s, "
,
p
.
blockThroughput
)
+
fmt
.
Sprintf
(
"receipts %3.2f/s, "
,
p
.
receiptThroughput
)
+
fmt
.
Sprintf
(
"states %3.2f/s, "
,
p
.
stateThroughput
)
+
fmt
.
Sprintf
(
"lacking %4d"
,
len
(
p
.
lacking
)),
)
}
// peerSet represents the collection of active peer participating in the
block
// peerSet represents the collection of active peer participating in the
chain
// download procedure.
type
peerSet
struct
{
peers
map
[
string
]
*
peer
...
...
@@ -359,7 +399,7 @@ func (ps *peerSet) Reset() {
// peer is already known.
//
// The method also sets the starting throughput values of the new peer to the
// average of all existing peers, to give it a realistic chan
g
e of being used
// average of all existing peers, to give it a realistic chan
c
e of being used
// for data retrievals.
func
(
ps
*
peerSet
)
Register
(
p
*
peer
)
error
{
ps
.
lock
.
Lock
()
...
...
@@ -369,15 +409,17 @@ func (ps *peerSet) Register(p *peer) error {
return
errAlreadyRegistered
}
if
len
(
ps
.
peers
)
>
0
{
p
.
blockThroughput
,
p
.
receiptThroughput
,
p
.
stateThroughput
=
0
,
0
,
0
p
.
headerThroughput
,
p
.
blockThroughput
,
p
.
receiptThroughput
,
p
.
stateThroughput
=
0
,
0
,
0
,
0
for
_
,
peer
:=
range
ps
.
peers
{
peer
.
lock
.
RLock
()
p
.
headerThroughput
+=
peer
.
headerThroughput
p
.
blockThroughput
+=
peer
.
blockThroughput
p
.
receiptThroughput
+=
peer
.
receiptThroughput
p
.
stateThroughput
+=
peer
.
stateThroughput
peer
.
lock
.
RUnlock
()
}
p
.
headerThroughput
/=
float64
(
len
(
ps
.
peers
))
p
.
blockThroughput
/=
float64
(
len
(
ps
.
peers
))
p
.
receiptThroughput
/=
float64
(
len
(
ps
.
peers
))
p
.
stateThroughput
/=
float64
(
len
(
ps
.
peers
))
...
...
@@ -441,6 +483,20 @@ func (ps *peerSet) BlockIdlePeers() ([]*peer, int) {
return
ps
.
idlePeers
(
61
,
61
,
idle
,
throughput
)
}
// HeaderIdlePeers retrieves a flat list of all the currently header-idle peers
// within the active peer set, ordered by their reputation.
func
(
ps
*
peerSet
)
HeaderIdlePeers
()
([]
*
peer
,
int
)
{
idle
:=
func
(
p
*
peer
)
bool
{
return
atomic
.
LoadInt32
(
&
p
.
headerIdle
)
==
0
}
throughput
:=
func
(
p
*
peer
)
float64
{
p
.
lock
.
RLock
()
defer
p
.
lock
.
RUnlock
()
return
p
.
headerThroughput
}
return
ps
.
idlePeers
(
62
,
64
,
idle
,
throughput
)
}
// BodyIdlePeers retrieves a flat list of all the currently body-idle peers within
// the active peer set, ordered by their reputation.
func
(
ps
*
peerSet
)
BodyIdlePeers
()
([]
*
peer
,
int
)
{
...
...
This diff is collapsed.
Click to expand it.
eth/downloader/queue.go
View file @
b40dc8a1
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment