Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
whqwjb
go-ethereum
提交
51b2f162
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,体验更适合开发者的 AI 搜索 >>
未验证
提交
51b2f162
编写于
11月 12, 2018
作者:
M
Martin Holst Swende
提交者:
Péter Szilágyi
11月 16, 2018
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
downloader: different sync strategy
上级
68be45e5
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
155 addition
and
39 deletion
+155
-39
eth/downloader/downloader.go
eth/downloader/downloader.go
+79
-39
eth/downloader/downloader_test.go
eth/downloader/downloader_test.go
+76
-0
未找到文件。
eth/downloader/downloader.go
浏览文件 @
51b2f162
...
...
@@ -430,7 +430,7 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td *big.I
}
height
:=
latest
.
Number
.
Uint64
()
origin
,
err
:=
d
.
findAncestor
(
p
,
heigh
t
)
origin
,
err
:=
d
.
findAncestor
(
p
,
lates
t
)
if
err
!=
nil
{
return
err
}
...
...
@@ -587,41 +587,85 @@ func (d *Downloader) fetchHeight(p *peerConnection) (*types.Header, error) {
}
}
// calculateRequestSpan calculates what headers to request from a peer when trying to determine the
// common ancestor.
// It returns parameters to be used for peer.RequestHeadersByNumber:
// from - starting block number
// count - number of headers to request
// skip - number of headers to skip
// and also returns 'max', the last block which is expected to be returned by the remote peers,
// given the (from,count,skip)
func
calculateRequestSpan
(
remoteHeight
,
localHeight
uint64
)
(
int64
,
int
,
int
,
uint64
)
{
var
(
from
int
count
int
MaxCount
=
MaxHeaderFetch
/
16
)
// requestHead is the highest block that we will ask for. If requestHead is not offset,
// the highest block that we will get is 16 blocks back from head, which means we
// will fetch 14 or 15 blocks unnecessarily in the case the height difference
// between us and the peer is 1-2 blocks, which is most common
requestHead
:=
int
(
remoteHeight
)
-
1
if
requestHead
<
0
{
requestHead
=
0
}
// requestBottom is the lowest block we want included in the query
// Ideally, we want to include just below own head
requestBottom
:=
int
(
localHeight
-
1
)
if
requestBottom
<
0
{
requestBottom
=
0
}
totalSpan
:=
requestHead
-
requestBottom
span
:=
1
+
totalSpan
/
MaxCount
if
span
<
2
{
span
=
2
}
if
span
>
16
{
span
=
16
}
count
=
1
+
totalSpan
/
span
if
count
>
MaxCount
{
count
=
MaxCount
}
if
count
<
2
{
count
=
2
}
from
=
requestHead
-
(
count
-
1
)
*
span
if
from
<
0
{
from
=
0
}
max
:=
from
+
(
count
-
1
)
*
span
return
int64
(
from
),
count
,
span
-
1
,
uint64
(
max
)
}
// findAncestor tries to locate the common ancestor link of the local chain and
// a remote peers blockchain. In the general case when our node was in sync and
// on the correct chain, checking the top N links should already get us a match.
// In the rare scenario when we ended up on a long reorganisation (i.e. none of
// the head links match), we do a binary search to find the common ancestor.
func
(
d
*
Downloader
)
findAncestor
(
p
*
peerConnection
,
height
uint64
)
(
uint64
,
error
)
{
func
(
d
*
Downloader
)
findAncestor
(
p
*
peerConnection
,
remoteHeader
*
types
.
Header
)
(
uint64
,
error
)
{
// Figure out the valid ancestor range to prevent rewrite attacks
floor
,
ceil
:=
int64
(
-
1
),
d
.
lightchain
.
CurrentHeader
()
.
Number
.
Uint64
()
if
d
.
mode
==
FullSync
{
ceil
=
d
.
blockchain
.
CurrentBlock
()
.
NumberU64
()
}
else
if
d
.
mode
==
FastSync
{
ceil
=
d
.
blockchain
.
CurrentFastBlock
()
.
NumberU64
()
var
(
floor
=
int64
(
-
1
)
localHeight
uint64
remoteHeight
=
remoteHeader
.
Number
.
Uint64
()
)
switch
d
.
mode
{
case
FullSync
:
localHeight
=
d
.
blockchain
.
CurrentBlock
()
.
NumberU64
()
case
FastSync
:
localHeight
=
d
.
blockchain
.
CurrentFastBlock
()
.
NumberU64
()
default
:
localHeight
=
d
.
lightchain
.
CurrentHeader
()
.
Number
.
Uint64
()
}
if
ceil
>=
MaxForkAncestry
{
floor
=
int64
(
ceil
-
MaxForkAncestry
)
p
.
log
.
Debug
(
"Looking for common ancestor"
,
"local"
,
localHeight
,
"remote"
,
remoteHeight
)
if
localHeight
>=
MaxForkAncestry
{
floor
=
int64
(
localHeight
-
MaxForkAncestry
)
}
p
.
log
.
Debug
(
"Looking for common ancestor"
,
"local"
,
ceil
,
"remote"
,
height
)
// Request the topmost blocks to short circuit binary ancestor lookup
head
:=
ceil
if
head
>
height
{
head
=
height
}
from
:=
int64
(
head
)
-
int64
(
MaxHeaderFetch
)
if
from
<
0
{
from
=
0
}
// Span out with 15 block gaps into the future to catch bad head reports
limit
:=
2
*
MaxHeaderFetch
/
16
count
:=
1
+
int
((
int64
(
ceil
)
-
from
)
/
16
)
if
count
>
limit
{
count
=
limit
}
go
p
.
peer
.
RequestHeadersByNumber
(
uint64
(
from
),
count
,
15
,
false
)
from
,
count
,
skip
,
max
:=
calculateRequestSpan
(
remoteHeight
,
localHeight
)
go
p
.
peer
.
RequestHeadersByNumber
(
uint64
(
from
),
count
,
skip
,
false
)
// Wait for the remote response to the head fetch
number
,
hash
:=
uint64
(
0
),
common
.
Hash
{}
...
...
@@ -647,9 +691,10 @@ func (d *Downloader) findAncestor(p *peerConnection, height uint64) (uint64, err
return
0
,
errEmptyHeaderSet
}
// Make sure the peer's reply conforms to the request
for
i
:=
0
;
i
<
len
(
headers
);
i
++
{
if
number
:=
headers
[
i
]
.
Number
.
Int64
();
number
!=
from
+
int64
(
i
)
*
16
{
p
.
log
.
Warn
(
"Head headers broke chain ordering"
,
"index"
,
i
,
"requested"
,
from
+
int64
(
i
)
*
16
,
"received"
,
number
)
for
i
,
header
:=
range
headers
{
expectNumber
:=
from
+
int64
(
i
)
*
int64
((
skip
+
1
))
if
number
:=
header
.
Number
.
Int64
();
number
!=
expectNumber
{
p
.
log
.
Warn
(
"Head headers broke chain ordering"
,
"index"
,
i
,
"requested"
,
expectNumber
,
"received"
,
number
)
return
0
,
errInvalidChain
}
}
...
...
@@ -657,20 +702,15 @@ func (d *Downloader) findAncestor(p *peerConnection, height uint64) (uint64, err
finished
=
true
for
i
:=
len
(
headers
)
-
1
;
i
>=
0
;
i
--
{
// Skip any headers that underflow/overflow our requested set
if
headers
[
i
]
.
Number
.
Int64
()
<
from
||
headers
[
i
]
.
Number
.
Uint64
()
>
ceil
{
if
headers
[
i
]
.
Number
.
Int64
()
<
from
||
headers
[
i
]
.
Number
.
Uint64
()
>
max
{
continue
}
// Otherwise check if we already know the header or not
h
:=
headers
[
i
]
.
Hash
()
n
:=
headers
[
i
]
.
Number
.
Uint64
()
if
(
d
.
mode
==
FullSync
&&
d
.
blockchain
.
HasBlock
(
h
,
n
))
||
(
d
.
mode
!=
FullSync
&&
d
.
lightchain
.
HasHeader
(
h
,
n
))
{
if
(
d
.
mode
==
FullSync
&&
d
.
blockchain
.
HasBlock
(
h
,
n
))
||
(
d
.
mode
!=
FullSync
&&
d
.
lightchain
.
HasHeader
(
h
,
n
))
{
number
,
hash
=
n
,
h
// If every header is known, even future ones, the peer straight out lied about its head
if
number
>
height
&&
i
==
limit
-
1
{
p
.
log
.
Warn
(
"Lied about chain head"
,
"reported"
,
height
,
"found"
,
number
)
return
0
,
errStallingPeer
}
break
}
}
...
...
@@ -694,7 +734,7 @@ func (d *Downloader) findAncestor(p *peerConnection, height uint64) (uint64, err
return
number
,
nil
}
// Ancestor not found, we need to binary search over our chain
start
,
end
:=
uint64
(
0
),
head
start
,
end
:=
uint64
(
0
),
remoteHeight
if
floor
>
0
{
start
=
uint64
(
floor
)
}
...
...
eth/downloader/downloader_test.go
浏览文件 @
51b2f162
...
...
@@ -20,6 +20,7 @@ import (
"errors"
"fmt"
"math/big"
"strings"
"sync"
"sync/atomic"
"testing"
...
...
@@ -1479,3 +1480,78 @@ func (ftp *floodingTestPeer) RequestHeadersByNumber(from uint64, count, skip int
}
return
nil
}
func
TestRemoteHeaderRequestSpan
(
t
*
testing
.
T
)
{
testCases
:=
[]
struct
{
remoteHeight
uint64
localHeight
uint64
expected
[]
int
}{
// Remote is way higher. We should ask for the remote head and go backwards
{
1500
,
1000
,
[]
int
{
1323
,
1339
,
1355
,
1371
,
1387
,
1403
,
1419
,
1435
,
1451
,
1467
,
1483
,
1499
},
},
{
15000
,
13006
,
[]
int
{
14823
,
14839
,
14855
,
14871
,
14887
,
14903
,
14919
,
14935
,
14951
,
14967
,
14983
,
14999
},
},
//Remote is pretty close to us. We don't have to fetch as many
{
1200
,
1150
,
[]
int
{
1149
,
1154
,
1159
,
1164
,
1169
,
1174
,
1179
,
1184
,
1189
,
1194
,
1199
},
},
// Remote is equal to us (so on a fork with higher td)
// We should get the closest couple of ancestors
{
1500
,
1500
,
[]
int
{
1497
,
1499
},
},
// We're higher than the remote! Odd
{
1000
,
1500
,
[]
int
{
997
,
999
},
},
// Check some weird edgecases that it behaves somewhat rationally
{
0
,
1500
,
[]
int
{
0
,
2
},
},
{
6000000
,
0
,
[]
int
{
5999823
,
5999839
,
5999855
,
5999871
,
5999887
,
5999903
,
5999919
,
5999935
,
5999951
,
5999967
,
5999983
,
5999999
},
},
{
0
,
0
,
[]
int
{
0
,
2
},
},
}
reqs
:=
func
(
from
,
count
,
span
int
)
[]
int
{
var
r
[]
int
num
:=
from
for
len
(
r
)
<
count
{
r
=
append
(
r
,
num
)
num
+=
span
+
1
}
return
r
}
for
i
,
tt
:=
range
testCases
{
from
,
count
,
span
,
max
:=
calculateRequestSpan
(
tt
.
remoteHeight
,
tt
.
localHeight
)
data
:=
reqs
(
int
(
from
),
count
,
span
)
if
max
!=
uint64
(
data
[
len
(
data
)
-
1
])
{
t
.
Errorf
(
"test %d: wrong last value %d != %d"
,
i
,
data
[
len
(
data
)
-
1
],
max
)
}
failed
:=
false
if
len
(
data
)
!=
len
(
tt
.
expected
)
{
failed
=
true
t
.
Errorf
(
"test %d: length wrong, expected %d got %d"
,
i
,
len
(
tt
.
expected
),
len
(
data
))
}
else
{
for
j
,
n
:=
range
data
{
if
n
!=
tt
.
expected
[
j
]
{
failed
=
true
break
}
}
}
if
failed
{
res
:=
strings
.
Replace
(
fmt
.
Sprint
(
data
),
" "
,
","
,
-
1
)
exp
:=
strings
.
Replace
(
fmt
.
Sprint
(
tt
.
expected
),
" "
,
","
,
-
1
)
fmt
.
Printf
(
"got: %v
\n
"
,
res
)
fmt
.
Printf
(
"exp: %v
\n
"
,
exp
)
t
.
Errorf
(
"test %d: wrong values"
,
i
)
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录