good morning!!!!
Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
B
bor
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package registry
Container registry
Harbor Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
open
bor
Commits
b86e7526
Commit
b86e7526
authored
Apr 24, 2015
by
Jeffrey Wilcke
Browse files
Options
Downloads
Patches
Plain Diff
eth, eth/downloader: moved peer selection to protocol handler
parent
9caf880f
Branches
Branches containing commit
Tags
Tags containing commit
No related merge requests found
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
eth/downloader/downloader.go
+50
-45
50 additions, 45 deletions
eth/downloader/downloader.go
eth/downloader/synchronous.go
+0
-79
0 additions, 79 deletions
eth/downloader/synchronous.go
eth/handler.go
+61
-4
61 additions, 4 deletions
eth/handler.go
eth/peer.go
+16
-6
16 additions, 6 deletions
eth/peer.go
with
127 additions
and
134 deletions
eth/downloader/downloader.go
+
50
−
45
View file @
b86e7526
...
@@ -89,7 +89,7 @@ func New(hasBlock hashCheckFn, insertChain chainInsertFn, currentTd currentTdFn)
...
@@ -89,7 +89,7 @@ func New(hasBlock hashCheckFn, insertChain chainInsertFn, currentTd currentTdFn)
blockCh
:
make
(
chan
blockPack
,
1
),
blockCh
:
make
(
chan
blockPack
,
1
),
quit
:
make
(
chan
struct
{}),
quit
:
make
(
chan
struct
{}),
}
}
go
downloader
.
peerHandler
()
//
go downloader.peerHandler()
go
downloader
.
update
()
go
downloader
.
update
()
return
downloader
return
downloader
...
@@ -110,7 +110,6 @@ func (d *Downloader) RegisterPeer(id string, td *big.Int, hash common.Hash, getH
...
@@ -110,7 +110,6 @@ func (d *Downloader) RegisterPeer(id string, td *big.Int, hash common.Hash, getH
// add peer to our peer set
// add peer to our peer set
d
.
peers
[
id
]
=
peer
d
.
peers
[
id
]
=
peer
// broadcast new peer
// broadcast new peer
d
.
newPeerCh
<-
peer
return
nil
return
nil
}
}
...
@@ -125,72 +124,78 @@ func (d *Downloader) UnregisterPeer(id string) {
...
@@ -125,72 +124,78 @@ func (d *Downloader) UnregisterPeer(id string) {
delete
(
d
.
peers
,
id
)
delete
(
d
.
peers
,
id
)
}
}
func
(
d
*
Downloader
)
peerHandler
()
{
func
(
d
*
Downloader
)
update
()
{
// itimer is used to determine when to start ignoring `minDesiredPeerCount`
itimer
:=
time
.
NewTimer
(
peerCountTimeout
)
out
:
out
:
for
{
for
{
select
{
select
{
case
<-
d
.
newPeerCh
:
case
sync
:=
<-
d
.
syncCh
:
// Meet the `minDesiredPeerCount` before we select our best peer
var
peer
*
peer
=
sync
.
peer
if
len
(
d
.
peers
)
<
minDesiredPeerCount
{
err
:=
d
.
getFromPeer
(
peer
,
sync
.
hash
,
sync
.
ignoreInitial
)
if
err
!=
nil
{
glog
.
V
(
logger
.
Detail
)
.
Infoln
(
err
)
break
break
}
}
itimer
.
Stop
()
d
.
selectPeer
(
d
.
peers
.
bestPeer
())
d
.
process
()
case
<-
itimer
.
C
:
// The timer will make sure that the downloader keeps an active state
// in which it attempts to always check the network for highest td peers
// Either select the peer or restart the timer if no peers could
// be selected.
if
peer
:=
d
.
peers
.
bestPeer
();
peer
!=
nil
{
d
.
selectPeer
(
d
.
peers
.
bestPeer
())
}
else
{
itimer
.
Reset
(
5
*
time
.
Second
)
}
case
<-
d
.
quit
:
case
<-
d
.
quit
:
break
out
break
out
}
}
}
}
}
}
func
(
d
*
Downloader
)
selectPeer
(
p
*
peer
)
{
// SynchroniseWithPeer will select the peer and use it for synchronising. If an empty string is given
// it will use the best peer possible and synchronise if it's TD is higher than our own. If any of the
// checks fail an error will be returned. This method is synchronous
func
(
d
*
Downloader
)
Synchronise
(
id
string
,
hash
common
.
Hash
)
(
types
.
Blocks
,
error
)
{
// Make sure it's doing neither. Once done we can restart the
// Make sure it's doing neither. Once done we can restart the
// downloading process if the TD is higher. For now just get on
// downloading process if the TD is higher. For now just get on
// with whatever is going on. This prevents unecessary switching.
// with whatever is going on. This prevents unecessary switching.
if
d
.
isBusy
()
{
if
d
.
isBusy
()
{
return
return
nil
,
errBusy
}
// selected peer must be better than our own
// XXX we also check the peer's recent hash to make sure we
// don't have it. Some peers report (i think) incorrect TD.
if
p
.
td
.
Cmp
(
d
.
currentTd
())
<=
0
||
d
.
hasBlock
(
p
.
recentHash
)
{
return
}
}
glog
.
V
(
logger
.
Detail
)
.
Infoln
(
"New peer with highest TD ="
,
p
.
td
)
// Fetch the peer using the id or throw an error if the peer couldn't be found
d
.
syncCh
<-
syncPack
{
p
,
p
.
recentHash
,
false
}
p
:=
d
.
peers
[
id
]
if
p
==
nil
{
return
nil
,
errUnknownPeer
}
}
func
(
d
*
Downloader
)
update
()
{
// Get the hash from the peer and initiate the downloading progress.
out
:
err
:=
d
.
getFromPeer
(
p
,
hash
,
false
)
for
{
select
{
case
sync
:=
<-
d
.
syncCh
:
var
peer
*
peer
=
sync
.
peer
err
:=
d
.
getFromPeer
(
peer
,
sync
.
hash
,
sync
.
ignoreInitial
)
if
err
!=
nil
{
if
err
!=
nil
{
glog
.
V
(
logger
.
Detail
)
.
Infoln
(
err
)
return
nil
,
err
break
}
}
d
.
process
()
return
d
.
queue
.
blocks
,
nil
case
<-
d
.
quit
:
}
break
out
func
(
d
*
Downloader
)
getFromPeer
(
p
*
peer
,
hash
common
.
Hash
,
ignoreInitial
bool
)
error
{
d
.
activePeer
=
p
.
id
glog
.
V
(
logger
.
Detail
)
.
Infoln
(
"Synchronising with the network using:"
,
p
.
id
)
// Start the fetcher. This will block the update entirely
// interupts need to be send to the appropriate channels
// respectively.
if
err
:=
d
.
startFetchingHashes
(
p
,
hash
,
ignoreInitial
);
err
!=
nil
{
// handle error
glog
.
V
(
logger
.
Debug
)
.
Infoln
(
"Error fetching hashes:"
,
err
)
// XXX Reset
return
err
}
}
// Start fetching blocks in paralel. The strategy is simple
// take any available peers, seserve a chunk for each peer available,
// let the peer deliver the chunkn and periodically check if a peer
// has timedout. When done downloading, process blocks.
if
err
:=
d
.
startFetchingBlocks
(
p
);
err
!=
nil
{
glog
.
V
(
logger
.
Debug
)
.
Infoln
(
"Error downloading blocks:"
,
err
)
// XXX reset
return
err
}
}
glog
.
V
(
logger
.
Detail
)
.
Infoln
(
"Sync completed"
)
return
nil
}
}
// XXX Make synchronous
// XXX Make synchronous
...
...
This diff is collapsed.
Click to expand it.
eth/downloader/synchronous.go
deleted
100644 → 0
+
0
−
79
View file @
9caf880f
package
downloader
import
(
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
)
// THIS IS PENDING AND TO DO CHANGES FOR MAKING THE DOWNLOADER SYNCHRONOUS
// SynchroniseWithPeer will select the peer and use it for synchronising. If an empty string is given
// it will use the best peer possible and synchronise if it's TD is higher than our own. If any of the
// checks fail an error will be returned. This method is synchronous
func
(
d
*
Downloader
)
SynchroniseWithPeer
(
id
string
)
(
types
.
Blocks
,
error
)
{
// Check if we're busy
if
d
.
isBusy
()
{
return
nil
,
errBusy
}
// Attempt to select a peer. This can either be nothing, which returns, best peer
// or selected peer. If no peer could be found an error will be returned
var
p
*
peer
if
len
(
id
)
==
0
{
p
=
d
.
peers
[
id
]
if
p
==
nil
{
return
nil
,
errUnknownPeer
}
}
else
{
p
=
d
.
peers
.
bestPeer
()
}
// Make sure our td is lower than the peer's td
if
p
.
td
.
Cmp
(
d
.
currentTd
())
<=
0
||
d
.
hasBlock
(
p
.
recentHash
)
{
return
nil
,
errLowTd
}
// Get the hash from the peer and initiate the downloading progress.
err
:=
d
.
getFromPeer
(
p
,
p
.
recentHash
,
false
)
if
err
!=
nil
{
return
nil
,
err
}
return
d
.
queue
.
blocks
,
nil
}
// Synchronise will synchronise using the best peer.
func
(
d
*
Downloader
)
Synchronise
()
(
types
.
Blocks
,
error
)
{
return
d
.
SynchroniseWithPeer
(
""
)
}
func
(
d
*
Downloader
)
getFromPeer
(
p
*
peer
,
hash
common
.
Hash
,
ignoreInitial
bool
)
error
{
d
.
activePeer
=
p
.
id
glog
.
V
(
logger
.
Detail
)
.
Infoln
(
"Synchronising with the network using:"
,
p
.
id
)
// Start the fetcher. This will block the update entirely
// interupts need to be send to the appropriate channels
// respectively.
if
err
:=
d
.
startFetchingHashes
(
p
,
hash
,
ignoreInitial
);
err
!=
nil
{
// handle error
glog
.
V
(
logger
.
Debug
)
.
Infoln
(
"Error fetching hashes:"
,
err
)
// XXX Reset
return
err
}
// Start fetching blocks in paralel. The strategy is simple
// take any available peers, seserve a chunk for each peer available,
// let the peer deliver the chunkn and periodically check if a peer
// has timedout. When done downloading, process blocks.
if
err
:=
d
.
startFetchingBlocks
(
p
);
err
!=
nil
{
glog
.
V
(
logger
.
Debug
)
.
Infoln
(
"Error downloading blocks:"
,
err
)
// XXX reset
return
err
}
glog
.
V
(
logger
.
Detail
)
.
Infoln
(
"Sync completed"
)
return
nil
}
This diff is collapsed.
Click to expand it.
eth/handler.go
+
61
−
4
View file @
b86e7526
...
@@ -39,6 +39,7 @@ import (
...
@@ -39,6 +39,7 @@ import (
"math"
"math"
"math/big"
"math/big"
"sync"
"sync"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core"
...
@@ -51,6 +52,11 @@ import (
...
@@ -51,6 +52,11 @@ import (
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rlp"
)
)
const
(
peerCountTimeout
=
12
*
time
.
Second
// Amount of time it takes for the peer handler to ignore minDesiredPeerCount
minDesiredPeerCount
=
5
// Amount of peers desired to start syncing
)
func
errResp
(
code
errCode
,
format
string
,
v
...
interface
{})
error
{
func
errResp
(
code
errCode
,
format
string
,
v
...
interface
{})
error
{
return
fmt
.
Errorf
(
"%v - %v"
,
code
,
fmt
.
Sprintf
(
format
,
v
...
))
return
fmt
.
Errorf
(
"%v - %v"
,
code
,
fmt
.
Sprintf
(
format
,
v
...
))
}
}
...
@@ -82,6 +88,9 @@ type ProtocolManager struct {
...
@@ -82,6 +88,9 @@ type ProtocolManager struct {
eventMux
*
event
.
TypeMux
eventMux
*
event
.
TypeMux
txSub
event
.
Subscription
txSub
event
.
Subscription
minedBlockSub
event
.
Subscription
minedBlockSub
event
.
Subscription
newPeerCh
chan
*
peer
quit
chan
struct
{}
}
}
// NewProtocolManager returns a new ethereum sub protocol manager. The Ethereum sub protocol manages peers capable
// NewProtocolManager returns a new ethereum sub protocol manager. The Ethereum sub protocol manages peers capable
...
@@ -93,7 +102,10 @@ func NewProtocolManager(protocolVersion, networkId int, mux *event.TypeMux, txpo
...
@@ -93,7 +102,10 @@ func NewProtocolManager(protocolVersion, networkId int, mux *event.TypeMux, txpo
chainman
:
chainman
,
chainman
:
chainman
,
downloader
:
downloader
,
downloader
:
downloader
,
peers
:
make
(
map
[
string
]
*
peer
),
peers
:
make
(
map
[
string
]
*
peer
),
newPeerCh
:
make
(
chan
*
peer
,
1
),
quit
:
make
(
chan
struct
{}),
}
}
go
manager
.
peerHandler
()
manager
.
SubProtocol
=
p2p
.
Protocol
{
manager
.
SubProtocol
=
p2p
.
Protocol
{
Name
:
"eth"
,
Name
:
"eth"
,
...
@@ -101,16 +113,61 @@ func NewProtocolManager(protocolVersion, networkId int, mux *event.TypeMux, txpo
...
@@ -101,16 +113,61 @@ func NewProtocolManager(protocolVersion, networkId int, mux *event.TypeMux, txpo
Length
:
ProtocolLength
,
Length
:
ProtocolLength
,
Run
:
func
(
p
*
p2p
.
Peer
,
rw
p2p
.
MsgReadWriter
)
error
{
Run
:
func
(
p
*
p2p
.
Peer
,
rw
p2p
.
MsgReadWriter
)
error
{
peer
:=
manager
.
newPeer
(
protocolVersion
,
networkId
,
p
,
rw
)
peer
:=
manager
.
newPeer
(
protocolVersion
,
networkId
,
p
,
rw
)
err
:=
manager
.
handle
(
peer
)
//glog.V(logger.Detail).Infof("[%s]: %v\n", peer.id, err)
return
err
manager
.
newPeerCh
<-
peer
return
manager
.
handle
(
peer
)
},
},
}
}
return
manager
return
manager
}
}
func
(
pm
*
ProtocolManager
)
peerHandler
()
{
// itimer is used to determine when to start ignoring `minDesiredPeerCount`
itimer
:=
time
.
NewTimer
(
peerCountTimeout
)
out
:
for
{
select
{
case
<-
pm
.
newPeerCh
:
// Meet the `minDesiredPeerCount` before we select our best peer
if
len
(
pm
.
peers
)
<
minDesiredPeerCount
{
break
}
itimer
.
Stop
()
// Find the best peer
peer
:=
getBestPeer
(
pm
.
peers
)
if
peer
==
nil
{
glog
.
V
(
logger
.
Debug
)
.
Infoln
(
"Sync attempt cancelled. No peers available"
)
return
}
go
pm
.
synchronise
(
peer
)
case
<-
itimer
.
C
:
// The timer will make sure that the downloader keeps an active state
// in which it attempts to always check the network for highest td peers
// Either select the peer or restart the timer if no peers could
// be selected.
if
peer
:=
getBestPeer
(
pm
.
peers
);
peer
!=
nil
{
go
pm
.
synchronise
(
peer
)
}
else
{
itimer
.
Reset
(
5
*
time
.
Second
)
}
case
<-
pm
.
quit
:
break
out
}
}
}
func
(
pm
*
ProtocolManager
)
synchronise
(
peer
*
peer
)
{
// Get the hashes from the peer (synchronously)
_
,
err
:=
pm
.
downloader
.
Synchronise
(
peer
.
id
,
peer
.
recentHash
)
if
err
!=
nil
{
// handle error
glog
.
V
(
logger
.
Debug
)
.
Infoln
(
"error downloading:"
,
err
)
}
}
func
(
pm
*
ProtocolManager
)
Start
()
{
func
(
pm
*
ProtocolManager
)
Start
()
{
// broadcast transactions
// broadcast transactions
pm
.
txSub
=
pm
.
eventMux
.
Subscribe
(
core
.
TxPreEvent
{})
pm
.
txSub
=
pm
.
eventMux
.
Subscribe
(
core
.
TxPreEvent
{})
...
@@ -141,7 +198,7 @@ func (pm *ProtocolManager) handle(p *peer) error {
...
@@ -141,7 +198,7 @@ func (pm *ProtocolManager) handle(p *peer) error {
pm
.
peers
[
p
.
id
]
=
p
pm
.
peers
[
p
.
id
]
=
p
pm
.
pmu
.
Unlock
()
pm
.
pmu
.
Unlock
()
pm
.
downloader
.
RegisterPeer
(
p
.
id
,
p
.
td
,
p
.
curr
entHash
,
p
.
requestHashes
,
p
.
requestBlocks
)
pm
.
downloader
.
RegisterPeer
(
p
.
id
,
p
.
td
,
p
.
rec
entHash
,
p
.
requestHashes
,
p
.
requestBlocks
)
defer
func
()
{
defer
func
()
{
pm
.
pmu
.
Lock
()
pm
.
pmu
.
Lock
()
defer
pm
.
pmu
.
Unlock
()
defer
pm
.
pmu
.
Unlock
()
...
...
This diff is collapsed.
Click to expand it.
eth/peer.go
+
16
−
6
View file @
b86e7526
...
@@ -25,6 +25,16 @@ type getBlockHashesMsgData struct {
...
@@ -25,6 +25,16 @@ type getBlockHashesMsgData struct {
Amount
uint64
Amount
uint64
}
}
func
getBestPeer
(
peers
map
[
string
]
*
peer
)
*
peer
{
var
peer
*
peer
for
_
,
cp
:=
range
peers
{
if
peer
==
nil
||
cp
.
td
.
Cmp
(
peer
.
td
)
>
0
{
peer
=
cp
}
}
return
peer
}
type
peer
struct
{
type
peer
struct
{
*
p2p
.
Peer
*
p2p
.
Peer
...
@@ -32,7 +42,7 @@ type peer struct {
...
@@ -32,7 +42,7 @@ type peer struct {
protv
,
netid
int
protv
,
netid
int
curr
entHash
common
.
Hash
rec
entHash
common
.
Hash
id
string
id
string
td
*
big
.
Int
td
*
big
.
Int
...
@@ -43,14 +53,14 @@ type peer struct {
...
@@ -43,14 +53,14 @@ type peer struct {
blockHashes
*
set
.
Set
blockHashes
*
set
.
Set
}
}
func
newPeer
(
protv
,
netid
int
,
genesis
,
curr
entHash
common
.
Hash
,
td
*
big
.
Int
,
p
*
p2p
.
Peer
,
rw
p2p
.
MsgReadWriter
)
*
peer
{
func
newPeer
(
protv
,
netid
int
,
genesis
,
rec
entHash
common
.
Hash
,
td
*
big
.
Int
,
p
*
p2p
.
Peer
,
rw
p2p
.
MsgReadWriter
)
*
peer
{
id
:=
p
.
ID
()
id
:=
p
.
ID
()
return
&
peer
{
return
&
peer
{
Peer
:
p
,
Peer
:
p
,
rw
:
rw
,
rw
:
rw
,
genesis
:
genesis
,
genesis
:
genesis
,
ourHash
:
curr
entHash
,
ourHash
:
rec
entHash
,
ourTd
:
td
,
ourTd
:
td
,
protv
:
protv
,
protv
:
protv
,
netid
:
netid
,
netid
:
netid
,
...
@@ -145,7 +155,7 @@ func (p *peer) handleStatus() error {
...
@@ -145,7 +155,7 @@ func (p *peer) handleStatus() error {
// Set the total difficulty of the peer
// Set the total difficulty of the peer
p
.
td
=
status
.
TD
p
.
td
=
status
.
TD
// set the best hash of the peer
// set the best hash of the peer
p
.
curr
entHash
=
status
.
CurrentBlock
p
.
rec
entHash
=
status
.
CurrentBlock
return
<-
errc
return
<-
errc
}
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment