good morning!!!!
Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
B
bor
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package registry
Container registry
Harbor Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
open
bor
Commits
7f00e8c0
Commit
7f00e8c0
authored
Jul 8, 2016
by
Péter Szilágyi
Browse files
Options
Downloads
Patches
Plain Diff
core, eth: enforce network split post DAO hard-fork
parent
a87089fd
Branches
Branches containing commit
Tags
Tags containing commit
No related merge requests found
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
core/block_validator.go
+7
-0
7 additions, 0 deletions
core/block_validator.go
eth/handler.go
+55
-3
55 additions, 3 deletions
eth/handler.go
eth/handler_test.go
+73
-0
73 additions, 0 deletions
eth/handler_test.go
eth/peer.go
+6
-4
6 additions, 4 deletions
eth/peer.go
with
141 additions
and
7 deletions
core/block_validator.go
+
7
−
0
View file @
7f00e8c0
...
...
@@ -248,6 +248,13 @@ func ValidateHeader(config *ChainConfig, pow pow.PoW, header *types.Header, pare
return
&
BlockNonceErr
{
header
.
Number
,
header
.
Hash
(),
header
.
Nonce
.
Uint64
()}
}
}
// If all checks passed, validate the extra-data field for hard forks
return
ValidateHeaderExtraData
(
config
,
header
)
}
// ValidateHeaderExtraData validates the extra-data field of a block header to
// ensure it conforms to hard-fork rules.
func
ValidateHeaderExtraData
(
config
*
ChainConfig
,
header
*
types
.
Header
)
error
{
// DAO hard-fork extension to the header validity: a) if the node is no-fork,
// do not accept blocks in the [fork, fork+10) range with the fork specific
// extra-data set; b) if the node is pro-fork, require blocks in the specific
...
...
This diff is collapsed.
Click to expand it.
eth/handler.go
+
55
−
3
View file @
7f00e8c0
...
...
@@ -45,6 +45,10 @@ const (
estHeaderRlpSize
=
500
// Approximate size of an RLP encoded block header
)
var
(
daoChallengeTimeout
=
15
*
time
.
Second
// Time allowance for a node to reply to the DAO handshake challenge
)
// errIncompatibleConfig is returned if the requested protocols and configs are
// not compatible (low protocol version restrictions and high requirements).
var
errIncompatibleConfig
=
errors
.
New
(
"incompatible configuration"
)
...
...
@@ -65,6 +69,7 @@ type ProtocolManager struct {
txpool
txPool
blockchain
*
core
.
BlockChain
chaindb
ethdb
.
Database
chainconfig
*
core
.
ChainConfig
downloader
*
downloader
.
Downloader
fetcher
*
fetcher
.
Fetcher
...
...
@@ -99,6 +104,7 @@ func NewProtocolManager(config *core.ChainConfig, fastSync bool, networkId int,
txpool
:
txpool
,
blockchain
:
blockchain
,
chaindb
:
chaindb
,
chainconfig
:
config
,
peers
:
newPeerSet
(),
newPeerCh
:
make
(
chan
*
peer
),
noMorePeers
:
make
(
chan
struct
{}),
...
...
@@ -278,6 +284,18 @@ func (pm *ProtocolManager) handle(p *peer) error {
// after this will be sent via broadcasts.
pm
.
syncTransactions
(
p
)
// If we're DAO hard-fork aware, validate any remote peer with regard to the hard-fork
if
daoBlock
:=
pm
.
chainconfig
.
DAOForkBlock
;
daoBlock
!=
nil
{
// Request the peer's DAO fork header for extra-data validation
if
err
:=
p
.
RequestHeadersByNumber
(
daoBlock
.
Uint64
(),
1
,
0
,
false
);
err
!=
nil
{
return
err
}
// Start a timer to disconnect if the peer doesn't reply in time
p
.
forkDrop
=
time
.
AfterFunc
(
daoChallengeTimeout
,
func
()
{
glog
.
V
(
logger
.
Warn
)
.
Infof
(
"%v: timed out DAO fork-check, dropping"
,
p
)
pm
.
removePeer
(
p
.
id
)
})
}
// main loop. handle incoming messages.
for
{
if
err
:=
pm
.
handleMsg
(
p
);
err
!=
nil
{
...
...
@@ -481,9 +499,43 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
if
err
:=
msg
.
Decode
(
&
headers
);
err
!=
nil
{
return
errResp
(
ErrDecode
,
"msg %v: %v"
,
msg
,
err
)
}
// If no headers were received, but we're expending a DAO fork check, maybe it's that
if
len
(
headers
)
==
0
&&
p
.
forkDrop
!=
nil
{
// Possibly an empty reply to the fork header checks, sanity check TDs
verifyDAO
:=
true
// If we already have a DAO header, we can check the peer's TD against it. If
// the peer's ahead of this, it too must have a reply to the DAO check
if
daoHeader
:=
pm
.
blockchain
.
GetHeaderByNumber
(
pm
.
chainconfig
.
DAOForkBlock
.
Uint64
());
daoHeader
!=
nil
{
if
p
.
Td
()
.
Cmp
(
pm
.
blockchain
.
GetTd
(
daoHeader
.
Hash
(),
daoHeader
.
Number
.
Uint64
()))
>=
0
{
verifyDAO
=
false
}
}
// If we're seemingly on the same chain, disable the drop timer
if
verifyDAO
{
glog
.
V
(
logger
.
Info
)
.
Infof
(
"%v: seems to be on the same side of the DAO fork"
,
p
)
p
.
forkDrop
.
Stop
()
p
.
forkDrop
=
nil
return
nil
}
}
// Filter out any explicitly requested headers, deliver the rest to the downloader
filter
:=
len
(
headers
)
==
1
if
filter
{
// If it's a potential DAO fork check, validate against the rules
if
p
.
forkDrop
!=
nil
&&
pm
.
chainconfig
.
DAOForkBlock
.
Cmp
(
headers
[
0
]
.
Number
)
==
0
{
// Disable the fork drop timer
p
.
forkDrop
.
Stop
()
p
.
forkDrop
=
nil
// Validate the header and either drop the peer or continue
if
err
:=
core
.
ValidateHeaderExtraData
(
pm
.
chainconfig
,
headers
[
0
]);
err
!=
nil
{
glog
.
V
(
logger
.
Info
)
.
Infof
(
"%v: verified to be on the other side of the DAO fork, dropping"
,
p
)
return
err
}
glog
.
V
(
logger
.
Info
)
.
Infof
(
"%v: verified to be on the same side of the DAO fork"
,
p
)
}
// Irrelevant of the fork checks, send the header to the fetcher just in case
headers
=
pm
.
fetcher
.
FilterHeaders
(
headers
,
time
.
Now
())
}
if
len
(
headers
)
>
0
||
!
filter
{
...
...
This diff is collapsed.
Click to expand it.
eth/handler_test.go
+
73
−
0
View file @
7f00e8c0
...
...
@@ -20,6 +20,7 @@ import (
"math/big"
"math/rand"
"testing"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
...
...
@@ -28,6 +29,7 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/params"
)
...
...
@@ -580,3 +582,74 @@ func testGetReceipt(t *testing.T, protocol int) {
t
.
Errorf
(
"receipts mismatch: %v"
,
err
)
}
}
// Tests that post eth protocol handshake, DAO fork-enabled clients also execute
// a DAO "challenge" verifying each others' DAO fork headers to ensure they're on
// compatible chains.
func
TestDAOChallengeNoVsNo
(
t
*
testing
.
T
)
{
testDAOChallenge
(
t
,
false
,
false
,
false
)
}
func
TestDAOChallengeNoVsPro
(
t
*
testing
.
T
)
{
testDAOChallenge
(
t
,
false
,
true
,
false
)
}
func
TestDAOChallengeProVsNo
(
t
*
testing
.
T
)
{
testDAOChallenge
(
t
,
true
,
false
,
false
)
}
func
TestDAOChallengeProVsPro
(
t
*
testing
.
T
)
{
testDAOChallenge
(
t
,
true
,
true
,
false
)
}
func
TestDAOChallengeNoVsTimeout
(
t
*
testing
.
T
)
{
testDAOChallenge
(
t
,
false
,
false
,
true
)
}
func
TestDAOChallengeProVsTimeout
(
t
*
testing
.
T
)
{
testDAOChallenge
(
t
,
true
,
true
,
true
)
}
func
testDAOChallenge
(
t
*
testing
.
T
,
localForked
,
remoteForked
bool
,
timeout
bool
)
{
// Reduce the DAO handshake challenge timeout
if
timeout
{
defer
func
(
old
time
.
Duration
)
{
daoChallengeTimeout
=
old
}(
daoChallengeTimeout
)
daoChallengeTimeout
=
500
*
time
.
Millisecond
}
// Create a DAO aware protocol manager
var
(
evmux
=
new
(
event
.
TypeMux
)
pow
=
new
(
core
.
FakePow
)
db
,
_
=
ethdb
.
NewMemDatabase
()
genesis
=
core
.
WriteGenesisBlockForTesting
(
db
)
config
=
&
core
.
ChainConfig
{
DAOForkBlock
:
big
.
NewInt
(
1
),
DAOForkSupport
:
localForked
}
blockchain
,
_
=
core
.
NewBlockChain
(
db
,
config
,
pow
,
evmux
)
)
pm
,
err
:=
NewProtocolManager
(
config
,
false
,
NetworkId
,
evmux
,
new
(
testTxPool
),
pow
,
blockchain
,
db
)
if
err
!=
nil
{
t
.
Fatalf
(
"failed to start test protocol manager: %v"
,
err
)
}
pm
.
Start
()
defer
pm
.
Stop
()
// Connect a new peer and check that we receive the DAO challenge
peer
,
_
:=
newTestPeer
(
"peer"
,
eth63
,
pm
,
true
)
defer
peer
.
close
()
challenge
:=
&
getBlockHeadersData
{
Origin
:
hashOrNumber
{
Number
:
config
.
DAOForkBlock
.
Uint64
()},
Amount
:
1
,
Skip
:
0
,
Reverse
:
false
,
}
if
err
:=
p2p
.
ExpectMsg
(
peer
.
app
,
GetBlockHeadersMsg
,
challenge
);
err
!=
nil
{
t
.
Fatalf
(
"challenge mismatch: %v"
,
err
)
}
// Create a block to reply to the challenge if no timeout is simualted
if
!
timeout
{
blocks
,
_
:=
core
.
GenerateChain
(
genesis
,
db
,
1
,
func
(
i
int
,
block
*
core
.
BlockGen
)
{
if
remoteForked
{
block
.
SetExtra
(
params
.
DAOForkBlockExtra
)
}
})
if
err
:=
p2p
.
Send
(
peer
.
app
,
BlockHeadersMsg
,
[]
*
types
.
Header
{
blocks
[
0
]
.
Header
()});
err
!=
nil
{
t
.
Fatalf
(
"failed to answer challenge: %v"
,
err
)
}
}
else
{
// Otherwise wait until the test timeout passes
time
.
Sleep
(
daoChallengeTimeout
+
500
*
time
.
Millisecond
)
}
// Verify that depending on fork side, the remote peer is maintained or dropped
if
localForked
==
remoteForked
&&
!
timeout
{
if
peers
:=
pm
.
peers
.
Len
();
peers
!=
1
{
t
.
Fatalf
(
"peer count mismatch: have %d, want %d"
,
peers
,
1
)
}
}
else
{
if
peers
:=
pm
.
peers
.
Len
();
peers
!=
0
{
t
.
Fatalf
(
"peer count mismatch: have %d, want %d"
,
peers
,
0
)
}
}
}
This diff is collapsed.
Click to expand it.
eth/peer.go
+
6
−
4
View file @
7f00e8c0
...
...
@@ -60,6 +60,8 @@ type peer struct {
rw
p2p
.
MsgReadWriter
version
int
// Protocol version negotiated
forkDrop
*
time
.
Timer
// Timed connection dropper if forks aren't validated in time
head
common
.
Hash
td
*
big
.
Int
lock
sync
.
RWMutex
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment