core/forkid: implement the forkid EIP, announce via ENR (#19738)

* eth: chain config (genesis + fork) ENR entry

* core/forkid, eth: protocol independent fork ID, update to CRC32 spec

* core/forkid, eth: make forkid a struct, next uint64, enr struct, RLP

* core/forkid: change forkhash rlp encoding from int to [4]byte

* eth: fixup eth entry a bit and update it every block

* eth: fix lint

* eth: fix crash in ethclient tests
This commit is contained in:
Péter Szilágyi
2019-07-08 18:53:47 +03:00
committed by GitHub
parent cc0f0e27a6
commit 983f92368b
11 changed files with 571 additions and 96 deletions

View File

@ -58,10 +58,6 @@ var (
syncChallengeTimeout = 15 * time.Second // Time allowance for a node to reply to the sync progress 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")
func errResp(code errCode, format string, v ...interface{}) error {
return fmt.Errorf("%v - %v", code, fmt.Sprintf(format, v...))
}
@ -75,17 +71,14 @@ type ProtocolManager struct {
checkpointNumber uint64 // Block number for the sync progress validator to cross reference
checkpointHash common.Hash // Block hash for the sync progress validator to cross reference
txpool txPool
blockchain *core.BlockChain
chainconfig *params.ChainConfig
maxPeers int
txpool txPool
blockchain *core.BlockChain
maxPeers int
downloader *downloader.Downloader
fetcher *fetcher.Fetcher
peers *peerSet
SubProtocols []p2p.Protocol
eventMux *event.TypeMux
txsCh chan core.NewTxsEvent
txsSub event.Subscription
@ -113,7 +106,6 @@ func NewProtocolManager(config *params.ChainConfig, checkpoint *params.TrustedCh
eventMux: mux,
txpool: txpool,
blockchain: blockchain,
chainconfig: config,
peers: newPeerSet(),
whitelist: whitelist,
newPeerCh: make(chan *peer),
@ -149,45 +141,7 @@ func NewProtocolManager(config *params.ChainConfig, checkpoint *params.TrustedCh
manager.checkpointNumber = (checkpoint.SectionIndex+1)*params.CHTFrequency - 1
manager.checkpointHash = checkpoint.SectionHead
}
// Initiate a sub-protocol for every implemented version we can handle
manager.SubProtocols = make([]p2p.Protocol, 0, len(ProtocolVersions))
for i, version := range ProtocolVersions {
// Skip protocol version if incompatible with the mode of operation
// TODO(karalabe): hard-drop eth/62 from the code base
if atomic.LoadUint32(&manager.fastSync) == 1 && version < eth63 {
continue
}
// Compatible; initialise the sub-protocol
version := version // Closure for the run
manager.SubProtocols = append(manager.SubProtocols, p2p.Protocol{
Name: ProtocolName,
Version: version,
Length: ProtocolLengths[i],
Run: func(p *p2p.Peer, rw p2p.MsgReadWriter) error {
peer := manager.newPeer(int(version), p, rw)
select {
case manager.newPeerCh <- peer:
manager.wg.Add(1)
defer manager.wg.Done()
return manager.handle(peer)
case <-manager.quitSync:
return p2p.DiscQuitting
}
},
NodeInfo: func() interface{} {
return manager.NodeInfo()
},
PeerInfo: func(id enode.ID) interface{} {
if p := manager.peers.Peer(fmt.Sprintf("%x", id[:8])); p != nil {
return p.Info()
}
return nil
},
})
}
if len(manager.SubProtocols) == 0 {
return nil, errIncompatibleConfig
}
// Construct the downloader (long sync) and its backing state bloom if fast
// sync is requested. The downloader is responsible for deallocating the state
// bloom when it's done.
@ -235,6 +189,39 @@ func NewProtocolManager(config *params.ChainConfig, checkpoint *params.TrustedCh
return manager, nil
}
func (pm *ProtocolManager) makeProtocol(version uint) p2p.Protocol {
length, ok := protocolLengths[version]
if !ok {
panic("makeProtocol for unknown version")
}
return p2p.Protocol{
Name: protocolName,
Version: version,
Length: length,
Run: func(p *p2p.Peer, rw p2p.MsgReadWriter) error {
peer := pm.newPeer(int(version), p, rw)
select {
case pm.newPeerCh <- peer:
pm.wg.Add(1)
defer pm.wg.Done()
return pm.handle(peer)
case <-pm.quitSync:
return p2p.DiscQuitting
}
},
NodeInfo: func() interface{} {
return pm.NodeInfo()
},
PeerInfo: func(id enode.ID) interface{} {
if p := pm.peers.Peer(fmt.Sprintf("%x", id[:8])); p != nil {
return p.Info()
}
return nil
},
}
}
func (pm *ProtocolManager) removePeer(id string) {
// Short circuit if the peer was already removed
peer := pm.peers.Peer(id)
@ -381,8 +368,8 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
if err != nil {
return err
}
if msg.Size > ProtocolMaxMsgSize {
return errResp(ErrMsgTooLarge, "%v > %v", msg.Size, ProtocolMaxMsgSize)
if msg.Size > protocolMaxMsgSize {
return errResp(ErrMsgTooLarge, "%v > %v", msg.Size, protocolMaxMsgSize)
}
defer msg.Discard()