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
63c6cedb
Commit
63c6cedb
authored
Jun 08, 2015
by
Péter Szilágyi
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
eth/downloader: cap the hash ban set, add test for it
parent
4b2dd447
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
64 additions
and
12 deletions
+64
-12
downloader.go
eth/downloader/downloader.go
+16
-7
downloader_test.go
eth/downloader/downloader_test.go
+43
-0
peer.go
eth/downloader/peer.go
+1
-1
queue.go
eth/downloader/queue.go
+1
-1
handler.go
eth/handler.go
+2
-2
peer.go
eth/peer.go
+1
-1
No files found.
eth/downloader/downloader.go
View file @
63c6cedb
...
@@ -17,18 +17,17 @@ import (
...
@@ -17,18 +17,17 @@ import (
"gopkg.in/fatih/set.v0"
"gopkg.in/fatih/set.v0"
)
)
const
(
var
(
MinHashFetch
=
512
// Minimum amount of hashes to not consider a peer stalling
MinHashFetch
=
512
// Minimum amount of hashes to not consider a peer stalling
MaxHashFetch
=
2048
// Amount of hashes to be fetched per retrieval request
MaxHashFetch
=
2048
// Amount of hashes to be fetched per retrieval request
MaxBlockFetch
=
128
// Amount of blocks to be fetched per retrieval request
MaxBlockFetch
=
128
// Amount of blocks to be fetched per retrieval request
hashTTL
=
5
*
time
.
Second
// Time it takes for a hash request to time out
hashTTL
=
5
*
time
.
Second
// Time it takes for a hash request to time out
)
var
(
blockSoftTTL
=
3
*
time
.
Second
// Request completion threshold for increasing or decreasing a peer's bandwidth
blockSoftTTL
=
3
*
time
.
Second
// Request completion threshold for increasing or decreasing a peer's bandwidth
blockHardTTL
=
3
*
blockSoftTTL
// Maximum time allowance before a block request is considered expired
blockHardTTL
=
3
*
blockSoftTTL
// Maximum time allowance before a block request is considered expired
crossCheckCycle
=
time
.
Second
// Period after which to check for expired cross checks
crossCheckCycle
=
time
.
Second
// Period after which to check for expired cross checks
maxBannedHashes
=
4096
// Number of bannable hashes before phasing old ones out
)
)
var
(
var
(
...
@@ -602,9 +601,19 @@ func (d *Downloader) banBlocks(peerId string, head common.Hash) error {
...
@@ -602,9 +601,19 @@ func (d *Downloader) banBlocks(peerId string, head common.Hash) error {
}
}
index
++
index
++
}
}
// Ban the head hash and phase out any excess
d
.
banned
.
Add
(
blocks
[
index
]
.
Hash
())
d
.
banned
.
Add
(
blocks
[
index
]
.
Hash
())
for
d
.
banned
.
Size
()
>
maxBannedHashes
{
glog
.
V
(
logger
.
Debug
)
.
Infof
(
"Banned %d blocks from: %s
\n
"
,
index
+
1
,
peerId
)
d
.
banned
.
Each
(
func
(
item
interface
{})
bool
{
// Skip any hard coded bans
if
core
.
BadHashes
[
item
.
(
common
.
Hash
)]
{
return
true
}
d
.
banned
.
Remove
(
item
)
return
false
})
}
glog
.
V
(
logger
.
Debug
)
.
Infof
(
"Banned %d blocks from: %s"
,
index
+
1
,
peerId
)
return
nil
return
nil
}
}
}
}
...
...
eth/downloader/downloader_test.go
View file @
63c6cedb
...
@@ -7,6 +7,7 @@ import (
...
@@ -7,6 +7,7 @@ import (
"time"
"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/types"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/event"
)
)
...
@@ -559,3 +560,45 @@ func TestBannedChainStarvationAttack(t *testing.T) {
...
@@ -559,3 +560,45 @@ func TestBannedChainStarvationAttack(t *testing.T) {
banned
=
bans
banned
=
bans
}
}
}
}
// Tests that if a peer sends excessively many/large invalid chains that are
// gradually banned, it will have an upper limit on the consumed memory and also
// the origin bad hashes will not be evacuated.
func
TestBannedChainMemoryExhaustionAttack
(
t
*
testing
.
T
)
{
// Reduce the test size a bit
MaxBlockFetch
=
4
maxBannedHashes
=
256
// Construct a banned chain with more chunks than the ban limit
hashes
:=
createHashes
(
0
,
maxBannedHashes
*
MaxBlockFetch
)
hashes
[
len
(
hashes
)
-
1
]
=
bannedHash
// weird index to have non multiple of ban chunk size
blocks
:=
createBlocksFromHashes
(
hashes
)
// Create the tester and ban the selected hash
tester
:=
newTester
(
t
,
hashes
,
blocks
)
tester
.
downloader
.
banned
.
Add
(
bannedHash
)
// Iteratively try to sync, and verify that the banned hash list grows until
// the head of the invalid chain is blocked too.
tester
.
newPeer
(
"attack"
,
big
.
NewInt
(
10000
),
hashes
[
0
])
for
{
// Try to sync with the attacker, check hash chain failure
if
_
,
err
:=
tester
.
syncTake
(
"attack"
,
hashes
[
0
]);
err
!=
ErrInvalidChain
{
t
.
Fatalf
(
"synchronisation error mismatch: have %v, want %v"
,
err
,
ErrInvalidChain
)
}
// Short circuit if the entire chain was banned
if
tester
.
downloader
.
banned
.
Has
(
hashes
[
0
])
{
break
}
// Otherwise ensure we never exceed the memory allowance and the hard coded bans are untouched
if
bans
:=
tester
.
downloader
.
banned
.
Size
();
bans
>
maxBannedHashes
{
t
.
Fatalf
(
"ban cap exceeded: have %v, want max %v"
,
bans
,
maxBannedHashes
)
}
for
hash
,
_
:=
range
core
.
BadHashes
{
if
!
tester
.
downloader
.
banned
.
Has
(
hash
)
{
t
.
Fatalf
(
"hard coded ban evacuated: %x"
,
hash
)
}
}
}
}
eth/downloader/peer.go
View file @
63c6cedb
...
@@ -94,7 +94,7 @@ func (p *peer) SetIdle() {
...
@@ -94,7 +94,7 @@ func (p *peer) SetIdle() {
for
{
for
{
// Calculate the new download bandwidth allowance
// Calculate the new download bandwidth allowance
prev
:=
atomic
.
LoadInt32
(
&
p
.
capacity
)
prev
:=
atomic
.
LoadInt32
(
&
p
.
capacity
)
next
:=
int32
(
math
.
Max
(
1
,
math
.
Min
(
MaxBlockFetch
,
float64
(
prev
)
*
scale
)))
next
:=
int32
(
math
.
Max
(
1
,
math
.
Min
(
float64
(
MaxBlockFetch
)
,
float64
(
prev
)
*
scale
)))
// Try to update the old value
// Try to update the old value
if
atomic
.
CompareAndSwapInt32
(
&
p
.
capacity
,
prev
,
next
)
{
if
atomic
.
CompareAndSwapInt32
(
&
p
.
capacity
,
prev
,
next
)
{
...
...
eth/downloader/queue.go
View file @
63c6cedb
...
@@ -16,7 +16,7 @@ import (
...
@@ -16,7 +16,7 @@ import (
"gopkg.in/karalabe/cookiejar.v2/collections/prque"
"gopkg.in/karalabe/cookiejar.v2/collections/prque"
)
)
const
(
var
(
blockCacheLimit
=
8
*
MaxBlockFetch
// Maximum number of blocks to cache before throttling the download
blockCacheLimit
=
8
*
MaxBlockFetch
// Maximum number of blocks to cache before throttling the download
)
)
...
...
eth/handler.go
View file @
63c6cedb
...
@@ -213,8 +213,8 @@ func (self *ProtocolManager) handleMsg(p *peer) error {
...
@@ -213,8 +213,8 @@ func (self *ProtocolManager) handleMsg(p *peer) error {
return
errResp
(
ErrDecode
,
"->msg %v: %v"
,
msg
,
err
)
return
errResp
(
ErrDecode
,
"->msg %v: %v"
,
msg
,
err
)
}
}
if
request
.
Amount
>
downloader
.
MaxHashFetch
{
if
request
.
Amount
>
uint64
(
downloader
.
MaxHashFetch
)
{
request
.
Amount
=
downloader
.
MaxHashFetch
request
.
Amount
=
uint64
(
downloader
.
MaxHashFetch
)
}
}
hashes
:=
self
.
chainman
.
GetBlockHashesFromHash
(
request
.
Hash
,
request
.
Amount
)
hashes
:=
self
.
chainman
.
GetBlockHashesFromHash
(
request
.
Hash
,
request
.
Amount
)
...
...
eth/peer.go
View file @
63c6cedb
...
@@ -102,7 +102,7 @@ func (p *peer) sendTransaction(tx *types.Transaction) error {
...
@@ -102,7 +102,7 @@ func (p *peer) sendTransaction(tx *types.Transaction) error {
func
(
p
*
peer
)
requestHashes
(
from
common
.
Hash
)
error
{
func
(
p
*
peer
)
requestHashes
(
from
common
.
Hash
)
error
{
glog
.
V
(
logger
.
Debug
)
.
Infof
(
"[%s] fetching hashes (%d) %x...
\n
"
,
p
.
id
,
downloader
.
MaxHashFetch
,
from
[
:
4
])
glog
.
V
(
logger
.
Debug
)
.
Infof
(
"[%s] fetching hashes (%d) %x...
\n
"
,
p
.
id
,
downloader
.
MaxHashFetch
,
from
[
:
4
])
return
p2p
.
Send
(
p
.
rw
,
GetBlockHashesMsg
,
getBlockHashesMsgData
{
from
,
downloader
.
MaxHashFetch
})
return
p2p
.
Send
(
p
.
rw
,
GetBlockHashesMsg
,
getBlockHashesMsgData
{
from
,
uint64
(
downloader
.
MaxHashFetch
)
})
}
}
func
(
p
*
peer
)
requestBlocks
(
hashes
[]
common
.
Hash
)
error
{
func
(
p
*
peer
)
requestBlocks
(
hashes
[]
common
.
Hash
)
error
{
...
...
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