consensus, eth: Istanbuil interface proposal

This commit is contained in:
kimmylin 2018-03-26 15:05:52 +08:00
parent 933972d139
commit b7b465c549
5 changed files with 81 additions and 3 deletions

View file

@ -21,6 +21,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
"math/big" "math/big"
@ -97,6 +98,34 @@ type Engine interface {
APIs(chain ChainReader) []rpc.API APIs(chain ChainReader) []rpc.API
} }
// Handler defines the interface to implement if a consensus engine needs to send/receive
// messages from peers.
type Handler interface {
// AddPeer adds a P2P peer
AddPeer(id string, peer Peer)
// RemovePeer removes a P2P peer
RemovePeer(id string)
// HandleMsg handles a message from peer
HandleMsg(data p2p.Msg) error
// SetBlockScheduler sets the scheduler for inserting a block after consensus is achieved.
SetBlockScheduler(scheduler BlockScheduler)
}
// BlockScheduler provides the interface that consensus engine needs to
// schedule for a future import of a block.
type BlockScheduler interface {
Enqueue(id string, block *types.Block) error
}
// Peer defines the interface to communicate with peers of the consensus engine.
type Peer interface {
// Send sends the message to this peer
Send(msgCode uint64, data interface{}) error
}
// PoW is a consensus engine based on proof-of-work. // PoW is a consensus engine based on proof-of-work.
type PoW interface { type PoW interface {
Engine Engine

View file

@ -130,7 +130,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
stopDbUpgrade: stopDbUpgrade, stopDbUpgrade: stopDbUpgrade,
networkId: config.NetworkId, networkId: config.NetworkId,
gasPrice: config.GasPrice, gasPrice: config.GasPrice,
etherbase: config.Etherbase, etherbase: determineEtherbase(ctx, config, chainConfig),
bloomRequests: make(chan chan *bloombits.Retrieval), bloomRequests: make(chan chan *bloombits.Retrieval),
bloomIndexer: NewBloomIndexer(chainDb, params.BloomBitsBlocks), bloomIndexer: NewBloomIndexer(chainDb, params.BloomBitsBlocks),
} }
@ -216,6 +216,10 @@ func CreateConsensusEngine(ctx *node.ServiceContext, config *ethash.Config, chai
if chainConfig.Clique != nil { if chainConfig.Clique != nil {
return clique.New(chainConfig.Clique, db) return clique.New(chainConfig.Clique, db)
} }
// If Istanbul is requested, set it up
//if chainConfig.Istanbul != nil {
// // Do something
//}
// Otherwise assume proof-of-work // Otherwise assume proof-of-work
switch { switch {
case config.PowMode == ethash.ModeFake: case config.PowMode == ethash.ModeFake:
@ -241,6 +245,14 @@ func CreateConsensusEngine(ctx *node.ServiceContext, config *ethash.Config, chai
} }
} }
func determineEtherbase(ctx *node.ServiceContext, config *Config, chainConfig *params.ChainConfig) common.Address {
// Force etherbase to node key address when using Istanbul
//if chainConfig.Istanbul != nil {
// return crypto.PubkeyToAddress(ctx.NodeKey().PublicKey)
//}
return config.Etherbase
}
// APIs returns the collection of RPC services the ethereum package offers. // APIs returns the collection of RPC services the ethereum package offers.
// NOTE, some of these services probably need to be moved to somewhere else. // NOTE, some of these services probably need to be moved to somewhere else.
func (s *Ethereum) APIs() []rpc.API { func (s *Ethereum) APIs() []rpc.API {
@ -328,6 +340,12 @@ func (s *Ethereum) Etherbase() (eb common.Address, err error) {
// set in js console via admin interface or wrapper from cli flags // set in js console via admin interface or wrapper from cli flags
func (self *Ethereum) SetEtherbase(etherbase common.Address) { func (self *Ethereum) SetEtherbase(etherbase common.Address) {
self.lock.Lock() self.lock.Lock()
// Disallow re-setting etherbase when using Istanbul
//if _, ok := self.engine.(consensus.Istanbul); ok {
// self.lock.Unlock()
// log.Error("Cannot set etherbase in Istanbul consensus")
// return
//}
self.etherbase = etherbase self.etherbase = etherbase
self.lock.Unlock() self.lock.Unlock()

View file

@ -94,6 +94,8 @@ type ProtocolManager struct {
// wait group is used for graceful shutdowns during downloading // wait group is used for graceful shutdowns during downloading
// and processing // and processing
wg sync.WaitGroup wg sync.WaitGroup
engine consensus.Engine
} }
// NewProtocolManager returns a new ethereum sub protocol manager. The Ethereum sub protocol manages peers capable // NewProtocolManager returns a new ethereum sub protocol manager. The Ethereum sub protocol manages peers capable
@ -111,6 +113,7 @@ func NewProtocolManager(config *params.ChainConfig, mode downloader.SyncMode, ne
noMorePeers: make(chan struct{}), noMorePeers: make(chan struct{}),
txsyncCh: make(chan *txsync), txsyncCh: make(chan *txsync),
quitSync: make(chan struct{}), quitSync: make(chan struct{}),
engine: engine,
} }
// Figure out whether to allow fast sync or not // Figure out whether to allow fast sync or not
if mode == downloader.FastSync && blockchain.CurrentBlock().NumberU64() > 0 { if mode == downloader.FastSync && blockchain.CurrentBlock().NumberU64() > 0 {
@ -177,6 +180,9 @@ func NewProtocolManager(config *params.ChainConfig, mode downloader.SyncMode, ne
return manager.blockchain.InsertChain(blocks) return manager.blockchain.InsertChain(blocks)
} }
manager.fetcher = fetcher.New(blockchain.GetBlockByHash, validator, manager.BroadcastBlock, heighter, inserter, manager.removePeer) manager.fetcher = fetcher.New(blockchain.GetBlockByHash, validator, manager.BroadcastBlock, heighter, inserter, manager.removePeer)
if handler, ok := manager.engine.(consensus.Handler); ok {
handler.SetBlockScheduler(manager.fetcher)
}
return manager, nil return manager, nil
} }
@ -191,6 +197,10 @@ func (pm *ProtocolManager) removePeer(id string) {
// Unregister the peer from the downloader and Ethereum peer set // Unregister the peer from the downloader and Ethereum peer set
pm.downloader.UnregisterPeer(id) pm.downloader.UnregisterPeer(id)
// Remove from the consensus engine's peer set
if handler, ok := pm.engine.(consensus.Handler); ok {
handler.RemovePeer(id)
}
if err := pm.peers.Unregister(id); err != nil { if err := pm.peers.Unregister(id); err != nil {
log.Error("Peer removal failed", "peer", id, "err", err) log.Error("Peer removal failed", "peer", id, "err", err)
} }
@ -275,6 +285,10 @@ func (pm *ProtocolManager) handle(p *peer) error {
p.Log().Error("Ethereum peer registration failed", "err", err) p.Log().Error("Ethereum peer registration failed", "err", err)
return err return err
} }
// Register the peer with the consensus engine
if handler, ok := pm.engine.(consensus.Handler); ok {
handler.AddPeer(p.id, p)
}
defer pm.removePeer(p.id) defer pm.removePeer(p.id)
// Register the peer in the downloader. If the downloader considers it banned, we disconnect // Register the peer in the downloader. If the downloader considers it banned, we disconnect
@ -673,6 +687,13 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
} }
pm.txpool.AddRemotes(txs) pm.txpool.AddRemotes(txs)
case msg.Code == ConsensusMsg:
if handler, ok := pm.engine.(consensus.Handler); ok {
if err := handler.HandleMsg(msg); err != nil {
return err
}
}
default: default:
return errResp(ErrInvalidMsgCode, "%v", msg.Code) return errResp(ErrInvalidMsgCode, "%v", msg.Code)
} }

View file

@ -130,6 +130,12 @@ func (p *peer) MarkTransaction(hash common.Hash) {
p.knownTxs.Add(hash) p.knownTxs.Add(hash)
} }
// Send writes an RLP-encoded message with the given code.
// data should encode as an RLP list.
func (p *peer) Send(msgCode uint64, data interface{}) error {
return p2p.Send(p.rw, msgCode, data)
}
// SendTransactions sends transactions to the peer and includes the hashes // SendTransactions sends transactions to the peer and includes the hashes
// in its transaction hash set for future reference. // in its transaction hash set for future reference.
func (p *peer) SendTransactions(txs types.Transactions) error { func (p *peer) SendTransactions(txs types.Transactions) error {

View file

@ -32,16 +32,17 @@ import (
const ( const (
eth62 = 62 eth62 = 62
eth63 = 63 eth63 = 63
eth64 = 64
) )
// Official short name of the protocol used during capability negotiation. // Official short name of the protocol used during capability negotiation.
var ProtocolName = "eth" var ProtocolName = "eth"
// Supported versions of the eth protocol (first is primary). // Supported versions of the eth protocol (first is primary).
var ProtocolVersions = []uint{eth63, eth62} var ProtocolVersions = []uint{eth64, eth63, eth62}
// Number of implemented message corresponding to different protocol versions. // Number of implemented message corresponding to different protocol versions.
var ProtocolLengths = []uint64{17, 8} var ProtocolLengths = []uint64{18, 17, 8}
const ProtocolMaxMsgSize = 10 * 1024 * 1024 // Maximum cap on the size of a protocol message const ProtocolMaxMsgSize = 10 * 1024 * 1024 // Maximum cap on the size of a protocol message
@ -62,6 +63,9 @@ const (
NodeDataMsg = 0x0e NodeDataMsg = 0x0e
GetReceiptsMsg = 0x0f GetReceiptsMsg = 0x0f
ReceiptsMsg = 0x10 ReceiptsMsg = 0x10
// Protocol messages belonging to eth/64
ConsensusMsg = 0x11
) )
type errCode int type errCode int