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
93422e9d
Unverified
Commit
93422e9d
authored
Oct 30, 2019
by
Péter Szilágyi
Committed by
GitHub
Oct 30, 2019
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #20140 from karalabe/eth64-handshake-forkid
eth: eth/64 - extend handshake with with fork id
parents
5d91accc
64571f93
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
304 additions
and
58 deletions
+304
-58
forkid.go
core/forkid/forkid.go
+4
-1
handler.go
eth/handler.go
+5
-2
handler_test.go
eth/handler_test.go
+4
-2
helper_test.go
eth/helper_test.go
+25
-8
peer.go
eth/peer.go
+76
-14
protocol.go
eth/protocol.go
+26
-18
protocol_test.go
eth/protocol_test.go
+164
-13
No files found.
core/forkid/forkid.go
View file @
93422e9d
...
...
@@ -50,6 +50,9 @@ type ID struct {
Next
uint64
// Block number of the next upcoming fork, or 0 if no forks are known
}
// Filter is a fork id filter to validate a remotely advertised ID.
type
Filter
func
(
id
ID
)
error
// NewID calculates the Ethereum fork ID from the chain config and head.
func
NewID
(
chain
*
core
.
BlockChain
)
ID
{
return
newID
(
...
...
@@ -82,7 +85,7 @@ func newID(config *params.ChainConfig, genesis common.Hash, head uint64) ID {
// NewFilter creates a filter that returns if a fork ID should be rejected or not
// based on the local chain's status.
func
NewFilter
(
chain
*
core
.
BlockChain
)
func
(
id
ID
)
erro
r
{
func
NewFilter
(
chain
*
core
.
BlockChain
)
Filte
r
{
return
newFilter
(
chain
.
Config
(),
chain
.
Genesis
()
.
Hash
(),
...
...
eth/handler.go
View file @
93422e9d
...
...
@@ -29,6 +29,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/forkid"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/eth/fetcher"
...
...
@@ -63,7 +64,8 @@ func errResp(code errCode, format string, v ...interface{}) error {
}
type
ProtocolManager
struct
{
networkID
uint64
networkID
uint64
forkFilter
forkid
.
Filter
// Fork ID filter, constant across the lifetime of the node
fastSync
uint32
// Flag whether fast sync is enabled (gets disabled if we already have blocks)
acceptTxs
uint32
// Flag whether we're considered synchronised (enables transaction processing)
...
...
@@ -103,6 +105,7 @@ func NewProtocolManager(config *params.ChainConfig, checkpoint *params.TrustedCh
// Create the protocol manager with the base fields
manager
:=
&
ProtocolManager
{
networkID
:
networkID
,
forkFilter
:
forkid
.
NewFilter
(
blockchain
),
eventMux
:
mux
,
txpool
:
txpool
,
blockchain
:
blockchain
,
...
...
@@ -304,7 +307,7 @@ func (pm *ProtocolManager) handle(p *peer) error {
number
=
head
.
Number
.
Uint64
()
td
=
pm
.
blockchain
.
GetTd
(
hash
,
number
)
)
if
err
:=
p
.
Handshake
(
pm
.
networkID
,
td
,
hash
,
genesis
.
Hash
());
err
!=
nil
{
if
err
:=
p
.
Handshake
(
pm
.
networkID
,
td
,
hash
,
genesis
.
Hash
()
,
forkid
.
NewID
(
pm
.
blockchain
),
pm
.
forkFilter
);
err
!=
nil
{
p
.
Log
()
.
Debug
(
"Ethereum handshake failed"
,
"err"
,
err
)
return
err
}
...
...
eth/handler_test.go
View file @
93422e9d
...
...
@@ -39,8 +39,8 @@ import (
)
// Tests that block headers can be retrieved from a remote chain based on user queries.
func
TestGetBlockHeaders62
(
t
*
testing
.
T
)
{
testGetBlockHeaders
(
t
,
62
)
}
func
TestGetBlockHeaders63
(
t
*
testing
.
T
)
{
testGetBlockHeaders
(
t
,
63
)
}
func
TestGetBlockHeaders64
(
t
*
testing
.
T
)
{
testGetBlockHeaders
(
t
,
64
)
}
func
testGetBlockHeaders
(
t
*
testing
.
T
,
protocol
int
)
{
pm
,
_
:=
newTestProtocolManagerMust
(
t
,
downloader
.
FullSync
,
downloader
.
MaxHashFetch
+
15
,
nil
,
nil
)
...
...
@@ -198,8 +198,8 @@ func testGetBlockHeaders(t *testing.T, protocol int) {
}
// Tests that block contents can be retrieved from a remote chain based on their hashes.
func
TestGetBlockBodies62
(
t
*
testing
.
T
)
{
testGetBlockBodies
(
t
,
62
)
}
func
TestGetBlockBodies63
(
t
*
testing
.
T
)
{
testGetBlockBodies
(
t
,
63
)
}
func
TestGetBlockBodies64
(
t
*
testing
.
T
)
{
testGetBlockBodies
(
t
,
64
)
}
func
testGetBlockBodies
(
t
*
testing
.
T
,
protocol
int
)
{
pm
,
_
:=
newTestProtocolManagerMust
(
t
,
downloader
.
FullSync
,
downloader
.
MaxBlockFetch
+
15
,
nil
,
nil
)
...
...
@@ -271,6 +271,7 @@ func testGetBlockBodies(t *testing.T, protocol int) {
// Tests that the node state database can be retrieved based on hashes.
func
TestGetNodeData63
(
t
*
testing
.
T
)
{
testGetNodeData
(
t
,
63
)
}
func
TestGetNodeData64
(
t
*
testing
.
T
)
{
testGetNodeData
(
t
,
64
)
}
func
testGetNodeData
(
t
*
testing
.
T
,
protocol
int
)
{
// Define three accounts to simulate transactions with
...
...
@@ -367,6 +368,7 @@ func testGetNodeData(t *testing.T, protocol int) {
// Tests that the transaction receipts can be retrieved based on hashes.
func
TestGetReceipt63
(
t
*
testing
.
T
)
{
testGetReceipt
(
t
,
63
)
}
func
TestGetReceipt64
(
t
*
testing
.
T
)
{
testGetReceipt
(
t
,
64
)
}
func
testGetReceipt
(
t
*
testing
.
T
,
protocol
int
)
{
// Define three accounts to simulate transactions with
...
...
eth/helper_test.go
View file @
93422e9d
...
...
@@ -22,6 +22,7 @@ package eth
import
(
"crypto/ecdsa"
"crypto/rand"
"fmt"
"math/big"
"sort"
"sync"
...
...
@@ -30,6 +31,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/forkid"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
...
...
@@ -171,20 +173,35 @@ func newTestPeer(name string, version int, pm *ProtocolManager, shake bool) (*te
head
=
pm
.
blockchain
.
CurrentHeader
()
td
=
pm
.
blockchain
.
GetTd
(
head
.
Hash
(),
head
.
Number
.
Uint64
())
)
tp
.
handshake
(
nil
,
td
,
head
.
Hash
(),
genesis
.
Hash
())
tp
.
handshake
(
nil
,
td
,
head
.
Hash
(),
genesis
.
Hash
()
,
forkid
.
NewID
(
pm
.
blockchain
),
forkid
.
NewFilter
(
pm
.
blockchain
)
)
}
return
tp
,
errc
}
// handshake simulates a trivial handshake that expects the same state from the
// remote side as we are simulating locally.
func
(
p
*
testPeer
)
handshake
(
t
*
testing
.
T
,
td
*
big
.
Int
,
head
common
.
Hash
,
genesis
common
.
Hash
)
{
msg
:=
&
statusData
{
ProtocolVersion
:
uint32
(
p
.
version
),
NetworkId
:
DefaultConfig
.
NetworkId
,
TD
:
td
,
CurrentBlock
:
head
,
GenesisBlock
:
genesis
,
func
(
p
*
testPeer
)
handshake
(
t
*
testing
.
T
,
td
*
big
.
Int
,
head
common
.
Hash
,
genesis
common
.
Hash
,
forkID
forkid
.
ID
,
forkFilter
forkid
.
Filter
)
{
var
msg
interface
{}
switch
{
case
p
.
version
==
eth63
:
msg
=
&
statusData63
{
ProtocolVersion
:
uint32
(
p
.
version
),
NetworkId
:
DefaultConfig
.
NetworkId
,
TD
:
td
,
CurrentBlock
:
head
,
GenesisBlock
:
genesis
,
}
case
p
.
version
==
eth64
:
msg
=
&
statusData
{
ProtocolVersion
:
uint32
(
p
.
version
),
NetworkID
:
DefaultConfig
.
NetworkId
,
TD
:
td
,
Head
:
head
,
Genesis
:
genesis
,
ForkID
:
forkID
,
}
default
:
panic
(
fmt
.
Sprintf
(
"unsupported eth protocol version: %d"
,
p
.
version
))
}
if
err
:=
p2p
.
ExpectMsg
(
p
.
app
,
StatusMsg
,
msg
);
err
!=
nil
{
t
.
Fatalf
(
"status recv: %v"
,
err
)
...
...
eth/peer.go
View file @
93422e9d
...
...
@@ -25,6 +25,7 @@ import (
mapset
"github.com/deckarep/golang-set"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/forkid"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/rlp"
...
...
@@ -353,22 +354,46 @@ func (p *peer) RequestReceipts(hashes []common.Hash) error {
// Handshake executes the eth protocol handshake, negotiating version number,
// network IDs, difficulties, head and genesis blocks.
func
(
p
*
peer
)
Handshake
(
network
uint64
,
td
*
big
.
Int
,
head
common
.
Hash
,
genesis
common
.
Hash
)
error
{
func
(
p
*
peer
)
Handshake
(
network
uint64
,
td
*
big
.
Int
,
head
common
.
Hash
,
genesis
common
.
Hash
,
forkID
forkid
.
ID
,
forkFilter
forkid
.
Filter
)
error
{
// Send out own handshake in a new thread
errc
:=
make
(
chan
error
,
2
)
var
status
statusData
// safe to read after two values have been received from errc
var
(
status63
statusData63
// safe to read after two values have been received from errc
status
statusData
// safe to read after two values have been received from errc
)
go
func
()
{
errc
<-
p2p
.
Send
(
p
.
rw
,
StatusMsg
,
&
statusData
{
ProtocolVersion
:
uint32
(
p
.
version
),
NetworkId
:
network
,
TD
:
td
,
CurrentBlock
:
head
,
GenesisBlock
:
genesis
,
})
switch
{
case
p
.
version
==
eth63
:
errc
<-
p2p
.
Send
(
p
.
rw
,
StatusMsg
,
&
statusData63
{
ProtocolVersion
:
uint32
(
p
.
version
),
NetworkId
:
network
,
TD
:
td
,
CurrentBlock
:
head
,
GenesisBlock
:
genesis
,
})
case
p
.
version
==
eth64
:
errc
<-
p2p
.
Send
(
p
.
rw
,
StatusMsg
,
&
statusData
{
ProtocolVersion
:
uint32
(
p
.
version
),
NetworkID
:
network
,
TD
:
td
,
Head
:
head
,
Genesis
:
genesis
,
ForkID
:
forkID
,
})
default
:
panic
(
fmt
.
Sprintf
(
"unsupported eth protocol version: %d"
,
p
.
version
))
}
}()
go
func
()
{
errc
<-
p
.
readStatus
(
network
,
&
status
,
genesis
)
switch
{
case
p
.
version
==
eth63
:
errc
<-
p
.
readStatusLegacy
(
network
,
&
status63
,
genesis
)
case
p
.
version
==
eth64
:
errc
<-
p
.
readStatus
(
network
,
&
status
,
genesis
,
forkFilter
)
default
:
panic
(
fmt
.
Sprintf
(
"unsupported eth protocol version: %d"
,
p
.
version
))
}
}()
timeout
:=
time
.
NewTimer
(
handshakeTimeout
)
defer
timeout
.
Stop
()
...
...
@@ -382,11 +407,18 @@ func (p *peer) Handshake(network uint64, td *big.Int, head common.Hash, genesis
return
p2p
.
DiscReadTimeout
}
}
p
.
td
,
p
.
head
=
status
.
TD
,
status
.
CurrentBlock
switch
{
case
p
.
version
==
eth63
:
p
.
td
,
p
.
head
=
status63
.
TD
,
status63
.
CurrentBlock
case
p
.
version
==
eth64
:
p
.
td
,
p
.
head
=
status
.
TD
,
status
.
Head
default
:
panic
(
fmt
.
Sprintf
(
"unsupported eth protocol version: %d"
,
p
.
version
))
}
return
nil
}
func
(
p
*
peer
)
readStatus
(
network
uint64
,
status
*
statusData
,
genesis
common
.
Hash
)
(
err
error
)
{
func
(
p
*
peer
)
readStatus
Legacy
(
network
uint64
,
status
*
statusData63
,
genesis
common
.
Hash
)
error
{
msg
,
err
:=
p
.
rw
.
ReadMsg
()
if
err
!=
nil
{
return
err
...
...
@@ -402,10 +434,10 @@ func (p *peer) readStatus(network uint64, status *statusData, genesis common.Has
return
errResp
(
ErrDecode
,
"msg %v: %v"
,
msg
,
err
)
}
if
status
.
GenesisBlock
!=
genesis
{
return
errResp
(
ErrGenesis
Block
Mismatch
,
"%x (!= %x)"
,
status
.
GenesisBlock
[
:
8
],
genesis
[
:
8
])
return
errResp
(
ErrGenesisMismatch
,
"%x (!= %x)"
,
status
.
GenesisBlock
[
:
8
],
genesis
[
:
8
])
}
if
status
.
NetworkId
!=
network
{
return
errResp
(
ErrNetworkI
d
Mismatch
,
"%d (!= %d)"
,
status
.
NetworkId
,
network
)
return
errResp
(
ErrNetworkI
D
Mismatch
,
"%d (!= %d)"
,
status
.
NetworkId
,
network
)
}
if
int
(
status
.
ProtocolVersion
)
!=
p
.
version
{
return
errResp
(
ErrProtocolVersionMismatch
,
"%d (!= %d)"
,
status
.
ProtocolVersion
,
p
.
version
)
...
...
@@ -413,6 +445,36 @@ func (p *peer) readStatus(network uint64, status *statusData, genesis common.Has
return
nil
}
func
(
p
*
peer
)
readStatus
(
network
uint64
,
status
*
statusData
,
genesis
common
.
Hash
,
forkFilter
forkid
.
Filter
)
error
{
msg
,
err
:=
p
.
rw
.
ReadMsg
()
if
err
!=
nil
{
return
err
}
if
msg
.
Code
!=
StatusMsg
{
return
errResp
(
ErrNoStatusMsg
,
"first msg has code %x (!= %x)"
,
msg
.
Code
,
StatusMsg
)
}
if
msg
.
Size
>
protocolMaxMsgSize
{
return
errResp
(
ErrMsgTooLarge
,
"%v > %v"
,
msg
.
Size
,
protocolMaxMsgSize
)
}
// Decode the handshake and make sure everything matches
if
err
:=
msg
.
Decode
(
&
status
);
err
!=
nil
{
return
errResp
(
ErrDecode
,
"msg %v: %v"
,
msg
,
err
)
}
if
status
.
NetworkID
!=
network
{
return
errResp
(
ErrNetworkIDMismatch
,
"%d (!= %d)"
,
status
.
NetworkID
,
network
)
}
if
int
(
status
.
ProtocolVersion
)
!=
p
.
version
{
return
errResp
(
ErrProtocolVersionMismatch
,
"%d (!= %d)"
,
status
.
ProtocolVersion
,
p
.
version
)
}
if
status
.
Genesis
!=
genesis
{
return
errResp
(
ErrGenesisMismatch
,
"%x (!= %x)"
,
status
.
Genesis
,
genesis
)
}
if
err
:=
forkFilter
(
status
.
ForkID
);
err
!=
nil
{
return
errResp
(
ErrForkIDRejected
,
"%v"
,
err
)
}
return
nil
}
// String implements fmt.Stringer.
func
(
p
*
peer
)
String
()
string
{
return
fmt
.
Sprintf
(
"Peer %s [%s]"
,
p
.
id
,
...
...
eth/protocol.go
View file @
93422e9d
...
...
@@ -23,6 +23,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/forkid"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/rlp"
...
...
@@ -30,24 +31,23 @@ import (
// Constants to match up protocol versions and messages
const
(
eth62
=
62
eth63
=
63
eth64
=
64
)
// protocolName is the official short name of the protocol used during capability negotiation.
const
protocolName
=
"eth"
// ProtocolVersions are the supported versions of the eth protocol (first is primary).
var
ProtocolVersions
=
[]
uint
{
eth63
}
var
ProtocolVersions
=
[]
uint
{
eth6
4
,
eth6
3
}
// protocolLengths are the number of implemented message corresponding to different protocol versions.
var
protocolLengths
=
map
[
uint
]
uint64
{
eth6
3
:
17
,
eth62
:
8
}
var
protocolLengths
=
map
[
uint
]
uint64
{
eth6
4
:
17
,
eth63
:
17
}
const
protocolMaxMsgSize
=
10
*
1024
*
1024
// Maximum cap on the size of a protocol message
// eth protocol message codes
const
(
// Protocol messages belonging to eth/62
StatusMsg
=
0x00
NewBlockHashesMsg
=
0x01
TxMsg
=
0x02
...
...
@@ -56,12 +56,10 @@ const (
GetBlockBodiesMsg
=
0x05
BlockBodiesMsg
=
0x06
NewBlockMsg
=
0x07
// Protocol messages belonging to eth/63
GetNodeDataMsg
=
0x0d
NodeDataMsg
=
0x0e
GetReceiptsMsg
=
0x0f
ReceiptsMsg
=
0x10
GetNodeDataMsg
=
0x0d
NodeDataMsg
=
0x0e
GetReceiptsMsg
=
0x0f
ReceiptsMsg
=
0x10
)
type
errCode
int
...
...
@@ -71,11 +69,11 @@ const (
ErrDecode
ErrInvalidMsgCode
ErrProtocolVersionMismatch
ErrNetworkIdMismatch
ErrGenesisBlockMismatch
ErrNetworkIDMismatch
ErrGenesisMismatch
ErrForkIDRejected
ErrNoStatusMsg
ErrExtraStatusMsg
ErrSuspendedPeer
)
func
(
e
errCode
)
String
()
string
{
...
...
@@ -88,11 +86,11 @@ var errorToString = map[int]string{
ErrDecode
:
"Invalid message"
,
ErrInvalidMsgCode
:
"Invalid message code"
,
ErrProtocolVersionMismatch
:
"Protocol version mismatch"
,
ErrNetworkIdMismatch
:
"NetworkId mismatch"
,
ErrGenesisBlockMismatch
:
"Genesis block mismatch"
,
ErrNetworkIDMismatch
:
"Network ID mismatch"
,
ErrGenesisMismatch
:
"Genesis mismatch"
,
ErrForkIDRejected
:
"Fork ID rejected"
,
ErrNoStatusMsg
:
"No status message"
,
ErrExtraStatusMsg
:
"Extra status message"
,
ErrSuspendedPeer
:
"Suspended peer"
,
}
type
txPool
interface
{
...
...
@@ -108,8 +106,8 @@ type txPool interface {
SubscribeNewTxsEvent
(
chan
<-
core
.
NewTxsEvent
)
event
.
Subscription
}
// statusData
is the network packet for the status message
.
type
statusData
struct
{
// statusData
63 is the network packet for the status message for eth/63
.
type
statusData
63
struct
{
ProtocolVersion
uint32
NetworkId
uint64
TD
*
big
.
Int
...
...
@@ -117,6 +115,16 @@ type statusData struct {
GenesisBlock
common
.
Hash
}
// statusData is the network packet for the status message for eth/64 and later.
type
statusData
struct
{
ProtocolVersion
uint32
NetworkID
uint64
TD
*
big
.
Int
Head
common
.
Hash
Genesis
common
.
Hash
ForkID
forkid
.
ID
}
// newBlockHashesData is the network packet for the block announcements.
type
newBlockHashesData
[]
struct
{
Hash
common
.
Hash
// Hash of one particular block being announced
...
...
eth/protocol_test.go
View file @
93422e9d
...
...
@@ -18,15 +18,24 @@ package eth
import
(
"fmt"
"math/big"
"sync"
"testing"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/forkid"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
)
...
...
@@ -37,10 +46,7 @@ func init() {
var
testAccount
,
_
=
crypto
.
HexToECDSA
(
"b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291"
)
// Tests that handshake failures are detected and reported correctly.
func
TestStatusMsgErrors62
(
t
*
testing
.
T
)
{
testStatusMsgErrors
(
t
,
62
)
}
func
TestStatusMsgErrors63
(
t
*
testing
.
T
)
{
testStatusMsgErrors
(
t
,
63
)
}
func
testStatusMsgErrors
(
t
*
testing
.
T
,
protocol
int
)
{
func
TestStatusMsgErrors63
(
t
*
testing
.
T
)
{
pm
,
_
:=
newTestProtocolManagerMust
(
t
,
downloader
.
FullSync
,
0
,
nil
,
nil
)
var
(
genesis
=
pm
.
blockchain
.
Genesis
()
...
...
@@ -59,21 +65,76 @@ func testStatusMsgErrors(t *testing.T, protocol int) {
wantError
:
errResp
(
ErrNoStatusMsg
,
"first msg has code 2 (!= 0)"
),
},
{
code
:
StatusMsg
,
data
:
statusData
{
10
,
DefaultConfig
.
NetworkId
,
td
,
head
.
Hash
(),
genesis
.
Hash
()},
wantError
:
errResp
(
ErrProtocolVersionMismatch
,
"10 (!= %d)"
,
protocol
),
code
:
StatusMsg
,
data
:
statusData
63
{
10
,
DefaultConfig
.
NetworkId
,
td
,
head
.
Hash
(),
genesis
.
Hash
()},
wantError
:
errResp
(
ErrProtocolVersionMismatch
,
"10 (!= %d)"
,
63
),
},
{
code
:
StatusMsg
,
data
:
statusData
{
uint32
(
protocol
)
,
999
,
td
,
head
.
Hash
(),
genesis
.
Hash
()},
wantError
:
errResp
(
ErrNetworkI
d
Mismatch
,
"999 (!= %d)"
,
DefaultConfig
.
NetworkId
),
code
:
StatusMsg
,
data
:
statusData
63
{
63
,
999
,
td
,
head
.
Hash
(),
genesis
.
Hash
()},
wantError
:
errResp
(
ErrNetworkI
D
Mismatch
,
"999 (!= %d)"
,
DefaultConfig
.
NetworkId
),
},
{
code
:
StatusMsg
,
data
:
statusData
{
uint32
(
protocol
)
,
DefaultConfig
.
NetworkId
,
td
,
head
.
Hash
(),
common
.
Hash
{
3
}},
wantError
:
errResp
(
ErrGenesis
Block
Mismatch
,
"0300000000000000 (!= %x)"
,
genesis
.
Hash
()
.
Bytes
()[
:
8
]),
code
:
StatusMsg
,
data
:
statusData
63
{
63
,
DefaultConfig
.
NetworkId
,
td
,
head
.
Hash
(),
common
.
Hash
{
3
}},
wantError
:
errResp
(
ErrGenesisMismatch
,
"0300000000000000 (!= %x)"
,
genesis
.
Hash
()
.
Bytes
()[
:
8
]),
},
}
for
i
,
test
:=
range
tests
{
p
,
errc
:=
newTestPeer
(
"peer"
,
63
,
pm
,
false
)
// The send call might hang until reset because
// the protocol might not read the payload.
go
p2p
.
Send
(
p
.
app
,
test
.
code
,
test
.
data
)
select
{
case
err
:=
<-
errc
:
if
err
==
nil
{
t
.
Errorf
(
"test %d: protocol returned nil error, want %q"
,
i
,
test
.
wantError
)
}
else
if
err
.
Error
()
!=
test
.
wantError
.
Error
()
{
t
.
Errorf
(
"test %d: wrong error: got %q, want %q"
,
i
,
err
,
test
.
wantError
)
}
case
<-
time
.
After
(
2
*
time
.
Second
)
:
t
.
Errorf
(
"protocol did not shut down within 2 seconds"
)
}
p
.
close
()
}
}
func
TestStatusMsgErrors64
(
t
*
testing
.
T
)
{
pm
,
_
:=
newTestProtocolManagerMust
(
t
,
downloader
.
FullSync
,
0
,
nil
,
nil
)
var
(
genesis
=
pm
.
blockchain
.
Genesis
()
head
=
pm
.
blockchain
.
CurrentHeader
()
td
=
pm
.
blockchain
.
GetTd
(
head
.
Hash
(),
head
.
Number
.
Uint64
())
forkID
=
forkid
.
NewID
(
pm
.
blockchain
)
)
defer
pm
.
Stop
()
tests
:=
[]
struct
{
code
uint64
data
interface
{}
wantError
error
}{
{
code
:
TxMsg
,
data
:
[]
interface
{}{},
wantError
:
errResp
(
ErrNoStatusMsg
,
"first msg has code 2 (!= 0)"
),
},
{
code
:
StatusMsg
,
data
:
statusData
{
10
,
DefaultConfig
.
NetworkId
,
td
,
head
.
Hash
(),
genesis
.
Hash
(),
forkID
},
wantError
:
errResp
(
ErrProtocolVersionMismatch
,
"10 (!= %d)"
,
64
),
},
{
code
:
StatusMsg
,
data
:
statusData
{
64
,
999
,
td
,
head
.
Hash
(),
genesis
.
Hash
(),
forkID
},
wantError
:
errResp
(
ErrNetworkIDMismatch
,
"999 (!= %d)"
,
DefaultConfig
.
NetworkId
),
},
{
code
:
StatusMsg
,
data
:
statusData
{
64
,
DefaultConfig
.
NetworkId
,
td
,
head
.
Hash
(),
common
.
Hash
{
3
},
forkID
},
wantError
:
errResp
(
ErrGenesisMismatch
,
"0300000000000000000000000000000000000000000000000000000000000000 (!= %x)"
,
genesis
.
Hash
()),
},
{
code
:
StatusMsg
,
data
:
statusData
{
64
,
DefaultConfig
.
NetworkId
,
td
,
head
.
Hash
(),
genesis
.
Hash
(),
forkid
.
ID
{
Hash
:
[
4
]
byte
{
0x00
,
0x01
,
0x02
,
0x03
}}},
wantError
:
errResp
(
ErrForkIDRejected
,
forkid
.
ErrLocalIncompatibleOrStale
.
Error
()),
},
}
for
i
,
test
:=
range
tests
{
p
,
errc
:=
newTestPeer
(
"peer"
,
protocol
,
pm
,
false
)
p
,
errc
:=
newTestPeer
(
"peer"
,
64
,
pm
,
false
)
// The send call might hang until reset because
// the protocol might not read the payload.
go
p2p
.
Send
(
p
.
app
,
test
.
code
,
test
.
data
)
...
...
@@ -92,9 +153,99 @@ func testStatusMsgErrors(t *testing.T, protocol int) {
}
}
func
TestForkIDSplit
(
t
*
testing
.
T
)
{
var
(
engine
=
ethash
.
NewFaker
()
configNoFork
=
&
params
.
ChainConfig
{
HomesteadBlock
:
big
.
NewInt
(
1
)}
configProFork
=
&
params
.
ChainConfig
{
HomesteadBlock
:
big
.
NewInt
(
1
),
EIP150Block
:
big
.
NewInt
(
2
),
EIP155Block
:
big
.
NewInt
(
2
),
EIP158Block
:
big
.
NewInt
(
2
),
ByzantiumBlock
:
big
.
NewInt
(
3
),
}
dbNoFork
=
rawdb
.
NewMemoryDatabase
()
dbProFork
=
rawdb
.
NewMemoryDatabase
()
gspecNoFork
=
&
core
.
Genesis
{
Config
:
configNoFork
}
gspecProFork
=
&
core
.
Genesis
{
Config
:
configProFork
}
genesisNoFork
=
gspecNoFork
.
MustCommit
(
dbNoFork
)
genesisProFork
=
gspecProFork
.
MustCommit
(
dbProFork
)
chainNoFork
,
_
=
core
.
NewBlockChain
(
dbNoFork
,
nil
,
configNoFork
,
engine
,
vm
.
Config
{},
nil
)
chainProFork
,
_
=
core
.
NewBlockChain
(
dbProFork
,
nil
,
configProFork
,
engine
,
vm
.
Config
{},
nil
)
blocksNoFork
,
_
=
core
.
GenerateChain
(
configNoFork
,
genesisNoFork
,
engine
,
dbNoFork
,
2
,
nil
)
blocksProFork
,
_
=
core
.
GenerateChain
(
configProFork
,
genesisProFork
,
engine
,
dbProFork
,
2
,
nil
)
ethNoFork
,
_
=
NewProtocolManager
(
configNoFork
,
nil
,
downloader
.
FullSync
,
1
,
new
(
event
.
TypeMux
),
new
(
testTxPool
),
engine
,
chainNoFork
,
dbNoFork
,
1
,
nil
)
ethProFork
,
_
=
NewProtocolManager
(
configProFork
,
nil
,
downloader
.
FullSync
,
1
,
new
(
event
.
TypeMux
),
new
(
testTxPool
),
engine
,
chainProFork
,
dbProFork
,
1
,
nil
)
)
ethNoFork
.
Start
(
1000
)
ethProFork
.
Start
(
1000
)
// Both nodes should allow the other to connect (same genesis, next fork is the same)
p2pNoFork
,
p2pProFork
:=
p2p
.
MsgPipe
()
peerNoFork
:=
newPeer
(
64
,
p2p
.
NewPeer
(
enode
.
ID
{
1
},
""
,
nil
),
p2pNoFork
)
peerProFork
:=
newPeer
(
64
,
p2p
.
NewPeer
(
enode
.
ID
{
2
},
""
,
nil
),
p2pProFork
)
errc
:=
make
(
chan
error
,
2
)
go
func
()
{
errc
<-
ethNoFork
.
handle
(
peerProFork
)
}()
go
func
()
{
errc
<-
ethProFork
.
handle
(
peerNoFork
)
}()
select
{
case
err
:=
<-
errc
:
t
.
Fatalf
(
"frontier nofork <-> profork failed: %v"
,
err
)
case
<-
time
.
After
(
250
*
time
.
Millisecond
)
:
p2pNoFork
.
Close
()
p2pProFork
.
Close
()
}
// Progress into Homestead. Fork's match, so we don't care what the future holds
chainNoFork
.
InsertChain
(
blocksNoFork
[
:
1
])
chainProFork
.
InsertChain
(
blocksProFork
[
:
1
])
p2pNoFork
,
p2pProFork
=
p2p
.
MsgPipe
()
peerNoFork
=
newPeer
(
64
,
p2p
.
NewPeer
(
enode
.
ID
{
1
},
""
,
nil
),
p2pNoFork
)
peerProFork
=
newPeer
(
64
,
p2p
.
NewPeer
(
enode
.
ID
{
2
},
""
,
nil
),
p2pProFork
)
errc
=
make
(
chan
error
,
2
)
go
func
()
{
errc
<-
ethNoFork
.
handle
(
peerProFork
)
}()
go
func
()
{
errc
<-
ethProFork
.
handle
(
peerNoFork
)
}()
select
{
case
err
:=
<-
errc
:
t
.
Fatalf
(
"homestead nofork <-> profork failed: %v"
,
err
)
case
<-
time
.
After
(
250
*
time
.
Millisecond
)
:
p2pNoFork
.
Close
()
p2pProFork
.
Close
()
}
// Progress into Spurious. Forks mismatch, signalling differing chains, reject
chainNoFork
.
InsertChain
(
blocksNoFork
[
1
:
2
])
chainProFork
.
InsertChain
(
blocksProFork
[
1
:
2
])
p2pNoFork
,
p2pProFork
=
p2p
.
MsgPipe
()
peerNoFork
=
newPeer
(
64
,
p2p
.
NewPeer
(
enode
.
ID
{
1
},
""
,
nil
),
p2pNoFork
)
peerProFork
=
newPeer
(
64
,
p2p
.
NewPeer
(
enode
.
ID
{
2
},
""
,
nil
),
p2pProFork
)
errc
=
make
(
chan
error
,
2
)
go
func
()
{
errc
<-
ethNoFork
.
handle
(
peerProFork
)
}()
go
func
()
{
errc
<-
ethProFork
.
handle
(
peerNoFork
)
}()
select
{
case
err
:=
<-
errc
:
if
want
:=
errResp
(
ErrForkIDRejected
,
forkid
.
ErrLocalIncompatibleOrStale
.
Error
());
err
.
Error
()
!=
want
.
Error
()
{
t
.
Fatalf
(
"fork ID rejection error mismatch: have %v, want %v"
,
err
,
want
)
}
case
<-
time
.
After
(
250
*
time
.
Millisecond
)
:
t
.
Fatalf
(
"split peers not rejected"
)
}
}
// This test checks that received transactions are added to the local pool.
func
TestRecvTransactions62
(
t
*
testing
.
T
)
{
testRecvTransactions
(
t
,
62
)
}
func
TestRecvTransactions63
(
t
*
testing
.
T
)
{
testRecvTransactions
(
t
,
63
)
}
func
TestRecvTransactions64
(
t
*
testing
.
T
)
{
testRecvTransactions
(
t
,
64
)
}
func
testRecvTransactions
(
t
*
testing
.
T
,
protocol
int
)
{
txAdded
:=
make
(
chan
[]
*
types
.
Transaction
)
...
...
@@ -121,8 +272,8 @@ func testRecvTransactions(t *testing.T, protocol int) {
}
// This test checks that pending transactions are sent.
func
TestSendTransactions62
(
t
*
testing
.
T
)
{
testSendTransactions
(
t
,
62
)
}
func
TestSendTransactions63
(
t
*
testing
.
T
)
{
testSendTransactions
(
t
,
63
)
}
func
TestSendTransactions64
(
t
*
testing
.
T
)
{
testSendTransactions
(
t
,
64
)
}
func
testSendTransactions
(
t
*
testing
.
T
,
protocol
int
)
{
pm
,
_
:=
newTestProtocolManagerMust
(
t
,
downloader
.
FullSync
,
0
,
nil
,
nil
)
...
...
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