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
2dd6a62f
Commit
2dd6a62f
authored
Jun 11, 2015
by
Péter Szilágyi
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
eth/downloader: support individual peers in the test suite
parent
29379032
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
113 additions
and
112 deletions
+113
-112
downloader_test.go
eth/downloader/downloader_test.go
+113
-112
No files found.
eth/downloader/downloader_test.go
View file @
2dd6a62f
...
@@ -16,6 +16,8 @@ var (
...
@@ -16,6 +16,8 @@ var (
knownHash
=
common
.
Hash
{
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
}
knownHash
=
common
.
Hash
{
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
}
unknownHash
=
common
.
Hash
{
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
}
unknownHash
=
common
.
Hash
{
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
,
9
}
bannedHash
=
common
.
Hash
{
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
}
bannedHash
=
common
.
Hash
{
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
}
genesis
=
createBlock
(
1
,
common
.
Hash
{},
knownHash
)
)
)
func
createHashes
(
start
,
amount
int
)
(
hashes
[]
common
.
Hash
)
{
func
createHashes
(
start
,
amount
int
)
(
hashes
[]
common
.
Hash
)
{
...
@@ -51,26 +53,20 @@ func createBlocksFromHashes(hashes []common.Hash) map[common.Hash]*types.Block {
...
@@ -51,26 +53,20 @@ func createBlocksFromHashes(hashes []common.Hash) map[common.Hash]*types.Block {
type
downloadTester
struct
{
type
downloadTester
struct
{
downloader
*
Downloader
downloader
*
Downloader
hashes
[]
common
.
Hash
// Chain of hashes simulating
ownHashes
[]
common
.
Hash
// Hash chain belonging to the tester
blocks
map
[
common
.
Hash
]
*
types
.
Block
// Blocks associated with the hashes
ownBlocks
map
[
common
.
Hash
]
*
types
.
Block
// Blocks belonging to the tester
chain
[]
common
.
Hash
// Block-chain being constructed
peerHashes
map
[
string
][]
common
.
Hash
// Hash chain belonging to different test peers
peerBlocks
map
[
string
]
map
[
common
.
Hash
]
*
types
.
Block
// Blocks belonging to different test peers
maxHashFetch
int
// Overrides the maximum number of retrieved hashes
maxHashFetch
int
// Overrides the maximum number of retrieved hashes
t
*
testing
.
T
done
chan
bool
activePeerId
string
}
}
func
newTester
(
t
*
testing
.
T
,
hashes
[]
common
.
Hash
,
blocks
map
[
common
.
Hash
]
*
types
.
Block
)
*
downloadTester
{
func
newTester
()
*
downloadTester
{
tester
:=
&
downloadTester
{
tester
:=
&
downloadTester
{
t
:
t
,
ownHashes
:
[]
common
.
Hash
{
knownHash
},
ownBlocks
:
map
[
common
.
Hash
]
*
types
.
Block
{
knownHash
:
genesis
},
hashes
:
hashes
,
peerHashes
:
make
(
map
[
string
][]
common
.
Hash
),
blocks
:
blocks
,
peerBlocks
:
make
(
map
[
string
]
map
[
common
.
Hash
]
*
types
.
Block
),
chain
:
[]
common
.
Hash
{
knownHash
},
done
:
make
(
chan
bool
),
}
}
var
mux
event
.
TypeMux
var
mux
event
.
TypeMux
downloader
:=
New
(
&
mux
,
tester
.
hasBlock
,
tester
.
getBlock
,
nil
)
downloader
:=
New
(
&
mux
,
tester
.
hasBlock
,
tester
.
getBlock
,
nil
)
...
@@ -79,13 +75,6 @@ func newTester(t *testing.T, hashes []common.Hash, blocks map[common.Hash]*types
...
@@ -79,13 +75,6 @@ func newTester(t *testing.T, hashes []common.Hash, blocks map[common.Hash]*types
return
tester
return
tester
}
}
// sync is a simple wrapper around the downloader to start synchronisation and
// block until it returns
func
(
dl
*
downloadTester
)
sync
(
peerId
string
,
head
common
.
Hash
)
error
{
dl
.
activePeerId
=
peerId
return
dl
.
downloader
.
synchronise
(
peerId
,
head
)
}
// syncTake is starts synchronising with a remote peer, but concurrently it also
// syncTake is starts synchronising with a remote peer, but concurrently it also
// starts fetching blocks that the downloader retrieved. IT blocks until both go
// starts fetching blocks that the downloader retrieved. IT blocks until both go
// routines terminate.
// routines terminate.
...
@@ -102,12 +91,17 @@ func (dl *downloadTester) syncTake(peerId string, head common.Hash) ([]*Block, e
...
@@ -102,12 +91,17 @@ func (dl *downloadTester) syncTake(peerId string, head common.Hash) ([]*Block, e
time
.
Sleep
(
time
.
Millisecond
)
time
.
Sleep
(
time
.
Millisecond
)
}
}
// Take a batch of blocks and accumulate
// Take a batch of blocks and accumulate
took
=
append
(
took
,
dl
.
downloader
.
TakeBlocks
()
...
)
blocks
:=
dl
.
downloader
.
TakeBlocks
()
for
_
,
block
:=
range
blocks
{
dl
.
ownHashes
=
append
(
dl
.
ownHashes
,
block
.
RawBlock
.
Hash
())
dl
.
ownBlocks
[
block
.
RawBlock
.
Hash
()]
=
block
.
RawBlock
}
took
=
append
(
took
,
blocks
...
)
}
}
done
<-
struct
{}{}
done
<-
struct
{}{}
}()
}()
// Start the downloading, sync the taker and return
// Start the downloading, sync the taker and return
err
:=
dl
.
sync
(
peerId
,
head
)
err
:=
dl
.
downloader
.
synchronise
(
peerId
,
head
)
done
<-
struct
{}{}
done
<-
struct
{}{}
<-
done
<-
done
...
@@ -115,65 +109,76 @@ func (dl *downloadTester) syncTake(peerId string, head common.Hash) ([]*Block, e
...
@@ -115,65 +109,76 @@ func (dl *downloadTester) syncTake(peerId string, head common.Hash) ([]*Block, e
return
took
,
err
return
took
,
err
}
}
// hasBlock checks if a block is present in the testers canonical chain.
func
(
dl
*
downloadTester
)
hasBlock
(
hash
common
.
Hash
)
bool
{
func
(
dl
*
downloadTester
)
hasBlock
(
hash
common
.
Hash
)
bool
{
for
_
,
h
:=
range
dl
.
chain
{
return
dl
.
getBlock
(
hash
)
!=
nil
if
h
==
hash
{
return
true
}
}
return
false
}
}
// getBlock retrieves a block from the testers canonical chain.
func
(
dl
*
downloadTester
)
getBlock
(
hash
common
.
Hash
)
*
types
.
Block
{
func
(
dl
*
downloadTester
)
getBlock
(
hash
common
.
Hash
)
*
types
.
Block
{
return
dl
.
blocks
[
knownHash
]
return
dl
.
ownBlocks
[
hash
]
}
// newPeer registers a new block download source into the downloader.
func
(
dl
*
downloadTester
)
newPeer
(
id
string
,
hashes
[]
common
.
Hash
,
blocks
map
[
common
.
Hash
]
*
types
.
Block
)
error
{
err
:=
dl
.
downloader
.
RegisterPeer
(
id
,
hashes
[
0
],
dl
.
peerGetHashesFn
(
id
),
dl
.
peerGetBlocksFn
(
id
))
if
err
==
nil
{
// Assign the owned hashes and blocks to the peer
dl
.
peerHashes
[
id
]
=
hashes
dl
.
peerBlocks
[
id
]
=
blocks
}
return
err
}
}
// getHashes retrieves a batch of hashes for reconstructing the chain.
// peerGetBlocksFn constructs a getHashes function associated with a particular
func
(
dl
*
downloadTester
)
getHashes
(
head
common
.
Hash
)
error
{
// peer in the download tester. The returned function can be used to retrieve
limit
:=
MaxHashFetch
// batches of hashes from the particularly requested peer.
if
dl
.
maxHashFetch
>
0
{
func
(
dl
*
downloadTester
)
peerGetHashesFn
(
id
string
)
func
(
head
common
.
Hash
)
error
{
limit
=
dl
.
maxHashFetch
return
func
(
head
common
.
Hash
)
error
{
}
limit
:=
MaxHashFetch
// Gather the next batch of hashes
if
dl
.
maxHashFetch
>
0
{
hashes
:=
make
([]
common
.
Hash
,
0
,
limit
)
limit
=
dl
.
maxHashFetch
for
i
,
hash
:=
range
dl
.
hashes
{
}
if
hash
==
head
{
// Gather the next batch of hashes
i
++
hashes
:=
dl
.
peerHashes
[
id
]
for
len
(
hashes
)
<
cap
(
hashes
)
&&
i
<
len
(
dl
.
hashes
)
{
result
:=
make
([]
common
.
Hash
,
0
,
limit
)
hashes
=
append
(
hashes
,
dl
.
hashes
[
i
])
for
i
,
hash
:=
range
hashes
{
if
hash
==
head
{
i
++
i
++
for
len
(
result
)
<
cap
(
result
)
&&
i
<
len
(
hashes
)
{
result
=
append
(
result
,
hashes
[
i
])
i
++
}
break
}
}
break
}
}
// Delay delivery a bit to allow attacks to unfold
go
func
()
{
time
.
Sleep
(
time
.
Millisecond
)
dl
.
downloader
.
DeliverHashes
(
id
,
result
)
}()
return
nil
}
}
// Delay delivery a bit to allow attacks to unfold
id
:=
dl
.
activePeerId
go
func
()
{
time
.
Sleep
(
time
.
Millisecond
)
dl
.
downloader
.
DeliverHashes
(
id
,
hashes
)
}()
return
nil
}
}
func
(
dl
*
downloadTester
)
getBlocks
(
id
string
)
func
([]
common
.
Hash
)
error
{
// peerGetBlocksFn constructs a getBlocks function associated with a particular
// peer in the download tester. The returned function can be used to retrieve
// batches of blocks from the particularly requested peer.
func
(
dl
*
downloadTester
)
peerGetBlocksFn
(
id
string
)
func
([]
common
.
Hash
)
error
{
return
func
(
hashes
[]
common
.
Hash
)
error
{
return
func
(
hashes
[]
common
.
Hash
)
error
{
blocks
:=
make
([]
*
types
.
Block
,
0
,
len
(
hashes
))
blocks
:=
dl
.
peerBlocks
[
id
]
result
:=
make
([]
*
types
.
Block
,
0
,
len
(
hashes
))
for
_
,
hash
:=
range
hashes
{
for
_
,
hash
:=
range
hashes
{
if
block
,
ok
:=
dl
.
blocks
[
hash
];
ok
{
if
block
,
ok
:=
blocks
[
hash
];
ok
{
blocks
=
append
(
blocks
,
block
)
result
=
append
(
result
,
block
)
}
}
}
}
go
dl
.
downloader
.
DeliverBlocks
(
id
,
blocks
)
go
dl
.
downloader
.
DeliverBlocks
(
id
,
result
)
return
nil
return
nil
}
}
}
}
// newPeer registers a new block download source into the syncer.
func
(
dl
*
downloadTester
)
newPeer
(
id
string
,
td
*
big
.
Int
,
hash
common
.
Hash
)
error
{
return
dl
.
downloader
.
RegisterPeer
(
id
,
hash
,
dl
.
getHashes
,
dl
.
getBlocks
(
id
))
}
// Tests that simple synchronization, without throttling from a good peer works.
// Tests that simple synchronization, without throttling from a good peer works.
func
TestSynchronisation
(
t
*
testing
.
T
)
{
func
TestSynchronisation
(
t
*
testing
.
T
)
{
// Create a small enough block chain to download and the tester
// Create a small enough block chain to download and the tester
...
@@ -181,11 +186,11 @@ func TestSynchronisation(t *testing.T) {
...
@@ -181,11 +186,11 @@ func TestSynchronisation(t *testing.T) {
hashes
:=
createHashes
(
0
,
targetBlocks
)
hashes
:=
createHashes
(
0
,
targetBlocks
)
blocks
:=
createBlocksFromHashes
(
hashes
)
blocks
:=
createBlocksFromHashes
(
hashes
)
tester
:=
newTester
(
t
,
hashes
,
blocks
)
tester
:=
newTester
()
tester
.
newPeer
(
"peer"
,
big
.
NewInt
(
10000
),
hashes
[
0
]
)
tester
.
newPeer
(
"peer"
,
hashes
,
blocks
)
// Synchronise with the peer and make sure all blocks were retrieved
// Synchronise with the peer and make sure all blocks were retrieved
if
err
:=
tester
.
sync
(
"peer"
,
hashes
[
0
]);
err
!=
nil
{
if
err
:=
tester
.
downloader
.
synchronise
(
"peer"
,
hashes
[
0
]);
err
!=
nil
{
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
}
}
if
queued
:=
len
(
tester
.
downloader
.
queue
.
blockPool
);
queued
!=
targetBlocks
{
if
queued
:=
len
(
tester
.
downloader
.
queue
.
blockPool
);
queued
!=
targetBlocks
{
...
@@ -200,11 +205,11 @@ func TestBlockTaking(t *testing.T) {
...
@@ -200,11 +205,11 @@ func TestBlockTaking(t *testing.T) {
hashes
:=
createHashes
(
0
,
targetBlocks
)
hashes
:=
createHashes
(
0
,
targetBlocks
)
blocks
:=
createBlocksFromHashes
(
hashes
)
blocks
:=
createBlocksFromHashes
(
hashes
)
tester
:=
newTester
(
t
,
hashes
,
blocks
)
tester
:=
newTester
()
tester
.
newPeer
(
"peer"
,
big
.
NewInt
(
10000
),
hashes
[
0
]
)
tester
.
newPeer
(
"peer"
,
hashes
,
blocks
)
// Synchronise with the peer and test block retrieval
// Synchronise with the peer and test block retrieval
if
err
:=
tester
.
sync
(
"peer"
,
hashes
[
0
]);
err
!=
nil
{
if
err
:=
tester
.
downloader
.
synchronise
(
"peer"
,
hashes
[
0
]);
err
!=
nil
{
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
}
}
if
took
:=
tester
.
downloader
.
TakeBlocks
();
len
(
took
)
!=
targetBlocks
{
if
took
:=
tester
.
downloader
.
TakeBlocks
();
len
(
took
)
!=
targetBlocks
{
...
@@ -214,7 +219,7 @@ func TestBlockTaking(t *testing.T) {
...
@@ -214,7 +219,7 @@ func TestBlockTaking(t *testing.T) {
// Tests that an inactive downloader will not accept incoming hashes and blocks.
// Tests that an inactive downloader will not accept incoming hashes and blocks.
func
TestInactiveDownloader
(
t
*
testing
.
T
)
{
func
TestInactiveDownloader
(
t
*
testing
.
T
)
{
tester
:=
newTester
(
t
,
nil
,
nil
)
tester
:=
newTester
()
// Check that neither hashes nor blocks are accepted
// Check that neither hashes nor blocks are accepted
if
err
:=
tester
.
downloader
.
DeliverHashes
(
"bad peer"
,
[]
common
.
Hash
{});
err
!=
errNoSyncActive
{
if
err
:=
tester
.
downloader
.
DeliverHashes
(
"bad peer"
,
[]
common
.
Hash
{});
err
!=
errNoSyncActive
{
...
@@ -232,11 +237,11 @@ func TestCancel(t *testing.T) {
...
@@ -232,11 +237,11 @@ func TestCancel(t *testing.T) {
hashes
:=
createHashes
(
0
,
targetBlocks
)
hashes
:=
createHashes
(
0
,
targetBlocks
)
blocks
:=
createBlocksFromHashes
(
hashes
)
blocks
:=
createBlocksFromHashes
(
hashes
)
tester
:=
newTester
(
t
,
hashes
,
blocks
)
tester
:=
newTester
()
tester
.
newPeer
(
"peer"
,
big
.
NewInt
(
10000
),
hashes
[
0
]
)
tester
.
newPeer
(
"peer"
,
hashes
,
blocks
)
// Synchronise with the peer, but cancel afterwards
// Synchronise with the peer, but cancel afterwards
if
err
:=
tester
.
sync
(
"peer"
,
hashes
[
0
]);
err
!=
nil
{
if
err
:=
tester
.
downloader
.
synchronise
(
"peer"
,
hashes
[
0
]);
err
!=
nil
{
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
}
}
if
!
tester
.
downloader
.
Cancel
()
{
if
!
tester
.
downloader
.
Cancel
()
{
...
@@ -260,13 +265,13 @@ func TestThrottling(t *testing.T) {
...
@@ -260,13 +265,13 @@ func TestThrottling(t *testing.T) {
hashes
:=
createHashes
(
0
,
targetBlocks
)
hashes
:=
createHashes
(
0
,
targetBlocks
)
blocks
:=
createBlocksFromHashes
(
hashes
)
blocks
:=
createBlocksFromHashes
(
hashes
)
tester
:=
newTester
(
t
,
hashes
,
blocks
)
tester
:=
newTester
()
tester
.
newPeer
(
"peer"
,
big
.
NewInt
(
10000
),
hashes
[
0
]
)
tester
.
newPeer
(
"peer"
,
hashes
,
blocks
)
// Start a synchronisation concurrently
// Start a synchronisation concurrently
errc
:=
make
(
chan
error
)
errc
:=
make
(
chan
error
)
go
func
()
{
go
func
()
{
errc
<-
tester
.
sync
(
"peer"
,
hashes
[
0
])
errc
<-
tester
.
downloader
.
synchronise
(
"peer"
,
hashes
[
0
])
}()
}()
// Iteratively take some blocks, always checking the retrieval count
// Iteratively take some blocks, always checking the retrieval count
for
total
:=
0
;
total
<
targetBlocks
;
{
for
total
:=
0
;
total
<
targetBlocks
;
{
...
@@ -303,9 +308,9 @@ func TestNonExistingParentAttack(t *testing.T) {
...
@@ -303,9 +308,9 @@ func TestNonExistingParentAttack(t *testing.T) {
forged
.
ParentHeaderHash
=
unknownHash
forged
.
ParentHeaderHash
=
unknownHash
// Try and sync with the malicious node and check that it fails
// Try and sync with the malicious node and check that it fails
tester
:=
newTester
(
t
,
hashes
,
blocks
)
tester
:=
newTester
()
tester
.
newPeer
(
"attack"
,
big
.
NewInt
(
10000
),
hashes
[
0
]
)
tester
.
newPeer
(
"attack"
,
hashes
,
blocks
)
if
err
:=
tester
.
sync
(
"attack"
,
hashes
[
0
]);
err
!=
nil
{
if
err
:=
tester
.
downloader
.
synchronise
(
"attack"
,
hashes
[
0
]);
err
!=
nil
{
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
}
}
bs
:=
tester
.
downloader
.
TakeBlocks
()
bs
:=
tester
.
downloader
.
TakeBlocks
()
...
@@ -319,8 +324,8 @@ func TestNonExistingParentAttack(t *testing.T) {
...
@@ -319,8 +324,8 @@ func TestNonExistingParentAttack(t *testing.T) {
// Reconstruct a valid chain, and try to synchronize with it
// Reconstruct a valid chain, and try to synchronize with it
forged
.
ParentHeaderHash
=
knownHash
forged
.
ParentHeaderHash
=
knownHash
tester
.
newPeer
(
"valid"
,
big
.
NewInt
(
20000
),
hashes
[
0
]
)
tester
.
newPeer
(
"valid"
,
hashes
,
blocks
)
if
err
:=
tester
.
sync
(
"valid"
,
hashes
[
0
]);
err
!=
nil
{
if
err
:=
tester
.
downloader
.
synchronise
(
"valid"
,
hashes
[
0
]);
err
!=
nil
{
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
}
}
bs
=
tester
.
downloader
.
TakeBlocks
()
bs
=
tester
.
downloader
.
TakeBlocks
()
...
@@ -341,12 +346,12 @@ func TestRepeatingHashAttack(t *testing.T) {
...
@@ -341,12 +346,12 @@ func TestRepeatingHashAttack(t *testing.T) {
forged
:=
hashes
[
:
len
(
hashes
)
-
1
]
forged
:=
hashes
[
:
len
(
hashes
)
-
1
]
// Try and sync with the malicious node
// Try and sync with the malicious node
tester
:=
newTester
(
t
,
forged
,
blocks
)
tester
:=
newTester
()
tester
.
newPeer
(
"attack"
,
big
.
NewInt
(
10000
),
forged
[
0
]
)
tester
.
newPeer
(
"attack"
,
forged
,
blocks
)
errc
:=
make
(
chan
error
)
errc
:=
make
(
chan
error
)
go
func
()
{
go
func
()
{
errc
<-
tester
.
sync
(
"attack"
,
hashes
[
0
])
errc
<-
tester
.
downloader
.
synchronise
(
"attack"
,
hashes
[
0
])
}()
}()
// Make sure that syncing returns and does so with a failure
// Make sure that syncing returns and does so with a failure
...
@@ -359,9 +364,8 @@ func TestRepeatingHashAttack(t *testing.T) {
...
@@ -359,9 +364,8 @@ func TestRepeatingHashAttack(t *testing.T) {
}
}
}
}
// Ensure that a valid chain can still pass sync
// Ensure that a valid chain can still pass sync
tester
.
hashes
=
hashes
tester
.
newPeer
(
"valid"
,
hashes
,
blocks
)
tester
.
newPeer
(
"valid"
,
big
.
NewInt
(
20000
),
hashes
[
0
])
if
err
:=
tester
.
downloader
.
synchronise
(
"valid"
,
hashes
[
0
]);
err
!=
nil
{
if
err
:=
tester
.
sync
(
"valid"
,
hashes
[
0
]);
err
!=
nil
{
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
}
}
}
}
...
@@ -377,15 +381,15 @@ func TestNonExistingBlockAttack(t *testing.T) {
...
@@ -377,15 +381,15 @@ func TestNonExistingBlockAttack(t *testing.T) {
hashes
[
len
(
hashes
)
/
2
]
=
unknownHash
hashes
[
len
(
hashes
)
/
2
]
=
unknownHash
// Try and sync with the malicious node and check that it fails
// Try and sync with the malicious node and check that it fails
tester
:=
newTester
(
t
,
hashes
,
blocks
)
tester
:=
newTester
()
tester
.
newPeer
(
"attack"
,
big
.
NewInt
(
10000
),
hashes
[
0
]
)
tester
.
newPeer
(
"attack"
,
hashes
,
blocks
)
if
err
:=
tester
.
sync
(
"attack"
,
hashes
[
0
]);
err
!=
errPeersUnavailable
{
if
err
:=
tester
.
downloader
.
synchronise
(
"attack"
,
hashes
[
0
]);
err
!=
errPeersUnavailable
{
t
.
Fatalf
(
"synchronisation error mismatch: have %v, want %v"
,
err
,
errPeersUnavailable
)
t
.
Fatalf
(
"synchronisation error mismatch: have %v, want %v"
,
err
,
errPeersUnavailable
)
}
}
// Ensure that a valid chain can still pass sync
// Ensure that a valid chain can still pass sync
hashes
[
len
(
hashes
)
/
2
]
=
origin
hashes
[
len
(
hashes
)
/
2
]
=
origin
tester
.
newPeer
(
"valid"
,
big
.
NewInt
(
20000
),
hashes
[
0
]
)
tester
.
newPeer
(
"valid"
,
hashes
,
blocks
)
if
err
:=
tester
.
sync
(
"valid"
,
hashes
[
0
]);
err
!=
nil
{
if
err
:=
tester
.
downloader
.
synchronise
(
"valid"
,
hashes
[
0
]);
err
!=
nil
{
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
}
}
}
}
...
@@ -408,14 +412,13 @@ func TestInvalidHashOrderAttack(t *testing.T) {
...
@@ -408,14 +412,13 @@ func TestInvalidHashOrderAttack(t *testing.T) {
copy
(
reverse
[
blockCacheLimit
:
],
chunk2
)
copy
(
reverse
[
blockCacheLimit
:
],
chunk2
)
// Try and sync with the malicious node and check that it fails
// Try and sync with the malicious node and check that it fails
tester
:=
newTester
(
t
,
reverse
,
blocks
)
tester
:=
newTester
()
tester
.
newPeer
(
"attack"
,
big
.
NewInt
(
10000
),
reverse
[
0
]
)
tester
.
newPeer
(
"attack"
,
reverse
,
blocks
)
if
_
,
err
:=
tester
.
syncTake
(
"attack"
,
reverse
[
0
]);
err
!=
errInvalidChain
{
if
_
,
err
:=
tester
.
syncTake
(
"attack"
,
reverse
[
0
]);
err
!=
errInvalidChain
{
t
.
Fatalf
(
"synchronisation error mismatch: have %v, want %v"
,
err
,
errInvalidChain
)
t
.
Fatalf
(
"synchronisation error mismatch: have %v, want %v"
,
err
,
errInvalidChain
)
}
}
// Ensure that a valid chain can still pass sync
// Ensure that a valid chain can still pass sync
tester
.
hashes
=
hashes
tester
.
newPeer
(
"valid"
,
hashes
,
blocks
)
tester
.
newPeer
(
"valid"
,
big
.
NewInt
(
20000
),
hashes
[
0
])
if
_
,
err
:=
tester
.
syncTake
(
"valid"
,
hashes
[
0
]);
err
!=
nil
{
if
_
,
err
:=
tester
.
syncTake
(
"valid"
,
hashes
[
0
]);
err
!=
nil
{
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
}
}
...
@@ -431,8 +434,8 @@ func TestMadeupHashChainAttack(t *testing.T) {
...
@@ -431,8 +434,8 @@ func TestMadeupHashChainAttack(t *testing.T) {
hashes
:=
createHashes
(
0
,
1024
*
blockCacheLimit
)
hashes
:=
createHashes
(
0
,
1024
*
blockCacheLimit
)
// Try and sync with the malicious node and check that it fails
// Try and sync with the malicious node and check that it fails
tester
:=
newTester
(
t
,
hashes
,
nil
)
tester
:=
newTester
()
tester
.
newPeer
(
"attack"
,
big
.
NewInt
(
10000
),
hashes
[
0
]
)
tester
.
newPeer
(
"attack"
,
hashes
,
nil
)
if
_
,
err
:=
tester
.
syncTake
(
"attack"
,
hashes
[
0
]);
err
!=
errCrossCheckFailed
{
if
_
,
err
:=
tester
.
syncTake
(
"attack"
,
hashes
[
0
]);
err
!=
errCrossCheckFailed
{
t
.
Fatalf
(
"synchronisation error mismatch: have %v, want %v"
,
err
,
errCrossCheckFailed
)
t
.
Fatalf
(
"synchronisation error mismatch: have %v, want %v"
,
err
,
errCrossCheckFailed
)
}
}
...
@@ -445,11 +448,11 @@ func TestMadeupHashChainAttack(t *testing.T) {
...
@@ -445,11 +448,11 @@ func TestMadeupHashChainAttack(t *testing.T) {
func
TestMadeupHashChainDrippingAttack
(
t
*
testing
.
T
)
{
func
TestMadeupHashChainDrippingAttack
(
t
*
testing
.
T
)
{
// Create a random chain of hashes to drip
// Create a random chain of hashes to drip
hashes
:=
createHashes
(
0
,
16
*
blockCacheLimit
)
hashes
:=
createHashes
(
0
,
16
*
blockCacheLimit
)
tester
:=
newTester
(
t
,
hashes
,
nil
)
tester
:=
newTester
()
// Try and sync with the attacker, one hash at a time
// Try and sync with the attacker, one hash at a time
tester
.
maxHashFetch
=
1
tester
.
maxHashFetch
=
1
tester
.
newPeer
(
"attack"
,
big
.
NewInt
(
10000
),
hashes
[
0
]
)
tester
.
newPeer
(
"attack"
,
hashes
,
nil
)
if
_
,
err
:=
tester
.
syncTake
(
"attack"
,
hashes
[
0
]);
err
!=
errStallingPeer
{
if
_
,
err
:=
tester
.
syncTake
(
"attack"
,
hashes
[
0
]);
err
!=
errStallingPeer
{
t
.
Fatalf
(
"synchronisation error mismatch: have %v, want %v"
,
err
,
errStallingPeer
)
t
.
Fatalf
(
"synchronisation error mismatch: have %v, want %v"
,
err
,
errStallingPeer
)
}
}
...
@@ -473,8 +476,8 @@ func TestMadeupBlockChainAttack(t *testing.T) {
...
@@ -473,8 +476,8 @@ func TestMadeupBlockChainAttack(t *testing.T) {
gapped
[
i
]
=
hashes
[
2
*
i
]
gapped
[
i
]
=
hashes
[
2
*
i
]
}
}
// Try and sync with the malicious node and check that it fails
// Try and sync with the malicious node and check that it fails
tester
:=
newTester
(
t
,
gapped
,
blocks
)
tester
:=
newTester
()
tester
.
newPeer
(
"attack"
,
big
.
NewInt
(
10000
),
gapped
[
0
]
)
tester
.
newPeer
(
"attack"
,
gapped
,
blocks
)
if
_
,
err
:=
tester
.
syncTake
(
"attack"
,
gapped
[
0
]);
err
!=
errCrossCheckFailed
{
if
_
,
err
:=
tester
.
syncTake
(
"attack"
,
gapped
[
0
]);
err
!=
errCrossCheckFailed
{
t
.
Fatalf
(
"synchronisation error mismatch: have %v, want %v"
,
err
,
errCrossCheckFailed
)
t
.
Fatalf
(
"synchronisation error mismatch: have %v, want %v"
,
err
,
errCrossCheckFailed
)
}
}
...
@@ -482,8 +485,7 @@ func TestMadeupBlockChainAttack(t *testing.T) {
...
@@ -482,8 +485,7 @@ func TestMadeupBlockChainAttack(t *testing.T) {
blockSoftTTL
=
defaultBlockTTL
blockSoftTTL
=
defaultBlockTTL
crossCheckCycle
=
defaultCrossCheckCycle
crossCheckCycle
=
defaultCrossCheckCycle
tester
.
hashes
=
hashes
tester
.
newPeer
(
"valid"
,
hashes
,
blocks
)
tester
.
newPeer
(
"valid"
,
big
.
NewInt
(
20000
),
hashes
[
0
])
if
_
,
err
:=
tester
.
syncTake
(
"valid"
,
hashes
[
0
]);
err
!=
nil
{
if
_
,
err
:=
tester
.
syncTake
(
"valid"
,
hashes
[
0
]);
err
!=
nil
{
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
}
}
...
@@ -507,8 +509,8 @@ func TestMadeupParentBlockChainAttack(t *testing.T) {
...
@@ -507,8 +509,8 @@ func TestMadeupParentBlockChainAttack(t *testing.T) {
block
.
ParentHeaderHash
=
hash
// Simulate pointing to already known hash
block
.
ParentHeaderHash
=
hash
// Simulate pointing to already known hash
}
}
// Try and sync with the malicious node and check that it fails
// Try and sync with the malicious node and check that it fails
tester
:=
newTester
(
t
,
hashes
,
forges
)
tester
:=
newTester
()
tester
.
newPeer
(
"attack"
,
big
.
NewInt
(
10000
),
hashes
[
0
]
)
tester
.
newPeer
(
"attack"
,
hashes
,
forges
)
if
_
,
err
:=
tester
.
syncTake
(
"attack"
,
hashes
[
0
]);
err
!=
errCrossCheckFailed
{
if
_
,
err
:=
tester
.
syncTake
(
"attack"
,
hashes
[
0
]);
err
!=
errCrossCheckFailed
{
t
.
Fatalf
(
"synchronisation error mismatch: have %v, want %v"
,
err
,
errCrossCheckFailed
)
t
.
Fatalf
(
"synchronisation error mismatch: have %v, want %v"
,
err
,
errCrossCheckFailed
)
}
}
...
@@ -516,8 +518,7 @@ func TestMadeupParentBlockChainAttack(t *testing.T) {
...
@@ -516,8 +518,7 @@ func TestMadeupParentBlockChainAttack(t *testing.T) {
blockSoftTTL
=
defaultBlockTTL
blockSoftTTL
=
defaultBlockTTL
crossCheckCycle
=
defaultCrossCheckCycle
crossCheckCycle
=
defaultCrossCheckCycle
tester
.
blocks
=
blocks
tester
.
newPeer
(
"valid"
,
hashes
,
blocks
)
tester
.
newPeer
(
"valid"
,
big
.
NewInt
(
20000
),
hashes
[
0
])
if
_
,
err
:=
tester
.
syncTake
(
"valid"
,
hashes
[
0
]);
err
!=
nil
{
if
_
,
err
:=
tester
.
syncTake
(
"valid"
,
hashes
[
0
]);
err
!=
nil
{
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
}
}
...
@@ -534,12 +535,12 @@ func TestBannedChainStarvationAttack(t *testing.T) {
...
@@ -534,12 +535,12 @@ func TestBannedChainStarvationAttack(t *testing.T) {
blocks
:=
createBlocksFromHashes
(
hashes
)
blocks
:=
createBlocksFromHashes
(
hashes
)
// Create the tester and ban the selected hash
// Create the tester and ban the selected hash
tester
:=
newTester
(
t
,
hashes
,
blocks
)
tester
:=
newTester
()
tester
.
downloader
.
banned
.
Add
(
bannedHash
)
tester
.
downloader
.
banned
.
Add
(
bannedHash
)
// Iteratively try to sync, and verify that the banned hash list grows until
// Iteratively try to sync, and verify that the banned hash list grows until
// the head of the invalid chain is blocked too.
// the head of the invalid chain is blocked too.
tester
.
newPeer
(
"attack"
,
big
.
NewInt
(
10000
),
hashes
[
0
]
)
tester
.
newPeer
(
"attack"
,
hashes
,
blocks
)
for
banned
:=
tester
.
downloader
.
banned
.
Size
();
;
{
for
banned
:=
tester
.
downloader
.
banned
.
Size
();
;
{
// Try to sync with the attacker, check hash chain failure
// Try to sync with the attacker, check hash chain failure
if
_
,
err
:=
tester
.
syncTake
(
"attack"
,
hashes
[
0
]);
err
!=
errInvalidChain
{
if
_
,
err
:=
tester
.
syncTake
(
"attack"
,
hashes
[
0
]);
err
!=
errInvalidChain
{
...
@@ -556,7 +557,7 @@ func TestBannedChainStarvationAttack(t *testing.T) {
...
@@ -556,7 +557,7 @@ func TestBannedChainStarvationAttack(t *testing.T) {
banned
=
bans
banned
=
bans
}
}
// Check that after banning an entire chain, bad peers get dropped
// Check that after banning an entire chain, bad peers get dropped
if
err
:=
tester
.
newPeer
(
"new attacker"
,
big
.
NewInt
(
10000
),
hashes
[
0
]
);
err
!=
errBannedHead
{
if
err
:=
tester
.
newPeer
(
"new attacker"
,
hashes
,
blocks
);
err
!=
errBannedHead
{
t
.
Fatalf
(
"peer registration mismatch: have %v, want %v"
,
err
,
errBannedHead
)
t
.
Fatalf
(
"peer registration mismatch: have %v, want %v"
,
err
,
errBannedHead
)
}
}
if
peer
:=
tester
.
downloader
.
peers
.
Peer
(
"net attacker"
);
peer
!=
nil
{
if
peer
:=
tester
.
downloader
.
peers
.
Peer
(
"net attacker"
);
peer
!=
nil
{
...
@@ -579,12 +580,12 @@ func TestBannedChainMemoryExhaustionAttack(t *testing.T) {
...
@@ -579,12 +580,12 @@ func TestBannedChainMemoryExhaustionAttack(t *testing.T) {
blocks
:=
createBlocksFromHashes
(
hashes
)
blocks
:=
createBlocksFromHashes
(
hashes
)
// Create the tester and ban the selected hash
// Create the tester and ban the selected hash
tester
:=
newTester
(
t
,
hashes
,
blocks
)
tester
:=
newTester
()
tester
.
downloader
.
banned
.
Add
(
bannedHash
)
tester
.
downloader
.
banned
.
Add
(
bannedHash
)
// Iteratively try to sync, and verify that the banned hash list grows until
// Iteratively try to sync, and verify that the banned hash list grows until
// the head of the invalid chain is blocked too.
// the head of the invalid chain is blocked too.
tester
.
newPeer
(
"attack"
,
big
.
NewInt
(
10000
),
hashes
[
0
]
)
tester
.
newPeer
(
"attack"
,
hashes
,
blocks
)
for
{
for
{
// Try to sync with the attacker, check hash chain failure
// Try to sync with the attacker, check hash chain failure
if
_
,
err
:=
tester
.
syncTake
(
"attack"
,
hashes
[
0
]);
err
!=
errInvalidChain
{
if
_
,
err
:=
tester
.
syncTake
(
"attack"
,
hashes
[
0
]);
err
!=
errInvalidChain
{
...
...
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