Skip to content

Commit 47a7fe5

Browse files
committed
eth: port the synchronisation algo to eth/62
1 parent ca88e18 commit 47a7fe5

File tree

10 files changed

+2010
-341
lines changed

10 files changed

+2010
-341
lines changed

cmd/utils/flags.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ var (
140140
}
141141
EthVersionFlag = cli.IntFlag{
142142
Name: "eth",
143-
Value: 61,
143+
Value: 62,
144144
Usage: "Highest eth protocol to advertise (temporary, dev option)",
145145
}
146146

core/types/block.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,20 @@ func (b *Block) WithMiningResult(nonce uint64, mixDigest common.Hash) *Block {
357357
}
358358
}
359359

360+
// WithBody returns a new block with the given transaction and uncle contents.
361+
func (b *Block) WithBody(transactions []*Transaction, uncles []*Header) *Block {
362+
block := &Block{
363+
header: copyHeader(b.header),
364+
transactions: make([]*Transaction, len(transactions)),
365+
uncles: make([]*Header, len(uncles)),
366+
}
367+
copy(block.transactions, transactions)
368+
for i := range uncles {
369+
block.uncles[i] = copyHeader(uncles[i])
370+
}
371+
return block
372+
}
373+
360374
// Implement pow.Block
361375

362376
func (b *Block) Hash() common.Hash {

eth/downloader/downloader.go

Lines changed: 580 additions & 94 deletions
Large diffs are not rendered by default.

eth/downloader/downloader_test.go

Lines changed: 259 additions & 78 deletions
Large diffs are not rendered by default.

eth/downloader/peer.go

Lines changed: 79 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,16 @@ import (
3131
"gopkg.in/fatih/set.v0"
3232
)
3333

34+
// Hash and block fetchers belonging to eth/61 and below
3435
type relativeHashFetcherFn func(common.Hash) error
3536
type absoluteHashFetcherFn func(uint64, int) error
3637
type blockFetcherFn func([]common.Hash) error
3738

39+
// Block header and body fethers belonging to eth/62 and above
40+
type relativeHeaderFetcherFn func(common.Hash, int, int, bool) error
41+
type absoluteHeaderFetcherFn func(uint64, int, int, bool) error
42+
type blockBodyFetcherFn func([]common.Hash) error
43+
3844
var (
3945
errAlreadyFetching = errors.New("already fetching blocks from peer")
4046
errAlreadyRegistered = errors.New("peer is already registered")
@@ -54,25 +60,37 @@ type peer struct {
5460

5561
ignored *set.Set // Set of hashes not to request (didn't have previously)
5662

57-
getRelHashes relativeHashFetcherFn // Method to retrieve a batch of hashes from an origin hash
58-
getAbsHashes absoluteHashFetcherFn // Method to retrieve a batch of hashes from an absolute position
59-
getBlocks blockFetcherFn // Method to retrieve a batch of blocks
63+
getRelHashes relativeHashFetcherFn // [eth/61] Method to retrieve a batch of hashes from an origin hash
64+
getAbsHashes absoluteHashFetcherFn // [eth/61] Method to retrieve a batch of hashes from an absolute position
65+
getBlocks blockFetcherFn // [eth/61] Method to retrieve a batch of blocks
66+
67+
getRelHeaders relativeHeaderFetcherFn // [eth/62] Method to retrieve a batch of headers from an origin hash
68+
getAbsHeaders absoluteHeaderFetcherFn // [eth/62] Method to retrieve a batch of headers from an absolute position
69+
getBlockBodies blockBodyFetcherFn // [eth/62] Method to retrieve a batch of block bodies
6070

6171
version int // Eth protocol version number to switch strategies
6272
}
6373

6474
// newPeer create a new downloader peer, with specific hash and block retrieval
6575
// mechanisms.
66-
func newPeer(id string, version int, head common.Hash, getRelHashes relativeHashFetcherFn, getAbsHashes absoluteHashFetcherFn, getBlocks blockFetcherFn) *peer {
76+
func newPeer(id string, version int, head common.Hash,
77+
getRelHashes relativeHashFetcherFn, getAbsHashes absoluteHashFetcherFn, getBlocks blockFetcherFn, // eth/61 callbacks, remove when upgrading
78+
getRelHeaders relativeHeaderFetcherFn, getAbsHeaders absoluteHeaderFetcherFn, getBlockBodies blockBodyFetcherFn) *peer {
6779
return &peer{
68-
id: id,
69-
head: head,
70-
capacity: 1,
80+
id: id,
81+
head: head,
82+
capacity: 1,
83+
ignored: set.New(),
84+
7185
getRelHashes: getRelHashes,
7286
getAbsHashes: getAbsHashes,
7387
getBlocks: getBlocks,
74-
ignored: set.New(),
75-
version: version,
88+
89+
getRelHeaders: getRelHeaders,
90+
getAbsHeaders: getAbsHeaders,
91+
getBlockBodies: getBlockBodies,
92+
93+
version: version,
7694
}
7795
}
7896

@@ -83,8 +101,8 @@ func (p *peer) Reset() {
83101
p.ignored.Clear()
84102
}
85103

86-
// Fetch sends a block retrieval request to the remote peer.
87-
func (p *peer) Fetch(request *fetchRequest) error {
104+
// Fetch61 sends a block retrieval request to the remote peer.
105+
func (p *peer) Fetch61(request *fetchRequest) error {
88106
// Short circuit if the peer is already fetching
89107
if !atomic.CompareAndSwapInt32(&p.idle, 0, 1) {
90108
return errAlreadyFetching
@@ -101,10 +119,28 @@ func (p *peer) Fetch(request *fetchRequest) error {
101119
return nil
102120
}
103121

104-
// SetIdle sets the peer to idle, allowing it to execute new retrieval requests.
122+
// Fetch sends a block body retrieval request to the remote peer.
123+
func (p *peer) Fetch(request *fetchRequest) error {
124+
// Short circuit if the peer is already fetching
125+
if !atomic.CompareAndSwapInt32(&p.idle, 0, 1) {
126+
return errAlreadyFetching
127+
}
128+
p.started = time.Now()
129+
130+
// Convert the header set to a retrievable slice
131+
hashes := make([]common.Hash, 0, len(request.Headers))
132+
for _, header := range request.Headers {
133+
hashes = append(hashes, header.Hash())
134+
}
135+
go p.getBlockBodies(hashes)
136+
137+
return nil
138+
}
139+
140+
// SetIdle61 sets the peer to idle, allowing it to execute new retrieval requests.
105141
// Its block retrieval allowance will also be updated either up- or downwards,
106142
// depending on whether the previous fetch completed in time or not.
107-
func (p *peer) SetIdle() {
143+
func (p *peer) SetIdle61() {
108144
// Update the peer's download allowance based on previous performance
109145
scale := 2.0
110146
if time.Since(p.started) > blockSoftTTL {
@@ -131,6 +167,36 @@ func (p *peer) SetIdle() {
131167
atomic.StoreInt32(&p.idle, 0)
132168
}
133169

170+
// SetIdle sets the peer to idle, allowing it to execute new retrieval requests.
171+
// Its block body retrieval allowance will also be updated either up- or downwards,
172+
// depending on whether the previous fetch completed in time or not.
173+
func (p *peer) SetIdle() {
174+
// Update the peer's download allowance based on previous performance
175+
scale := 2.0
176+
if time.Since(p.started) > bodySoftTTL {
177+
scale = 0.5
178+
if time.Since(p.started) > bodyHardTTL {
179+
scale = 1 / float64(MaxBodyFetch) // reduces capacity to 1
180+
}
181+
}
182+
for {
183+
// Calculate the new download bandwidth allowance
184+
prev := atomic.LoadInt32(&p.capacity)
185+
next := int32(math.Max(1, math.Min(float64(MaxBodyFetch), float64(prev)*scale)))
186+
187+
// Try to update the old value
188+
if atomic.CompareAndSwapInt32(&p.capacity, prev, next) {
189+
// If we're having problems at 1 capacity, try to find better peers
190+
if next == 1 {
191+
p.Demote()
192+
}
193+
break
194+
}
195+
}
196+
// Set the peer to idle to allow further block requests
197+
atomic.StoreInt32(&p.idle, 0)
198+
}
199+
134200
// Capacity retrieves the peers block download allowance based on its previously
135201
// discovered bandwidth capacity.
136202
func (p *peer) Capacity() int {

0 commit comments

Comments
 (0)