eth: eth/64 - extend handshake packet with fork id
This commit is contained in:
90
eth/peer.go
90
eth/peer.go
@ -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) readStatusLegacy(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(ErrGenesisBlockMismatch, "%x (!= %x)", status.GenesisBlock[:8], genesis[:8])
|
||||
return errResp(ErrGenesisMismatch, "%x (!= %x)", status.GenesisBlock[:8], genesis[:8])
|
||||
}
|
||||
if status.NetworkId != network {
|
||||
return errResp(ErrNetworkIdMismatch, "%d (!= %d)", 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)
|
||||
@ -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,
|
||||
|
Reference in New Issue
Block a user