During blockchain download the node compares its current cumulative di

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
During blockchain download, the node compares its current cumulative
difficulty with that of the peer from which it is downloading, but
doesn't compare that peer's cumulative difficulty with the difficulty of
other peers. This allows a rogue peer to trick a node that is more than
720 blocks behind the current main chain, or especially a node that is
downloading the blockchain from scratch, to download a fork that is
worse (in difficulty) than the main one, and get permanently stuck into
that fork, if it is more than 720 blocks away from the common block with
the main chain. For example, a rogue peer may decide to expose test net
to main net, and any new node that starts to download from it will get
stuck on the test net chain.
Our only protection against such attack now, as far as I can tell, is
the use of hallmarks, which increases the probability that a new node
will download its blockchain from a trusted peer. But this is not a very
good solution.
What I propose to change, in 1.4 release:
Limit the number of blocks downloaded from a single peer to 719 at a
time, so that a single bad peer cannot make you go into a
non-resolvable fork. Currently a node can download up to 10*1440 blocks
from the same peer before trying another one.
Before attempting each download of one or more (up to 719) blocks from
a peer, query at least Math.min(10, totalNumberOfConnectedPeers) other
peers, and select to download from the peer that has the best
difficulty, at a height not exceeding 719 blocks from the common block
with that peer. If after the download it turns out the peer lied about
its difficulty, pop off the downloaded blocks and blacklist.
The downside is that this will slow down blockchain download and
increase network traffic. It will also slow down block propagation at
the end of the blockchain, because even for a single block fetch the
node would need to query many peers first (this could be optimized
though, require best peer selection only when downloading more than 10
blocks at a time for example).
Any better suggestions, or flaws with my proposal?