diff --git a/eth/handler.go b/eth/handler.go index 2988939441e62..500f8e0811938 100644 --- a/eth/handler.go +++ b/eth/handler.go @@ -81,7 +81,7 @@ type HandlerConfig handlerConfig // node network handler. type handlerConfig struct { Database ethdb.Database // Database for direct sync insertions - Chain *core.BlockChain // Blockchain to serve data from + Chain eth.HandlerBlockchain // Blockchain to serve data from TxPool txPool // Transaction pool to propagate from Merger *consensus.Merger // The manager for eth1/2 transition Network uint64 // Network identifier to adfvertise @@ -92,6 +92,20 @@ type handlerConfig struct { Whitelist map[uint64]common.Hash // Hard coded whitelist for sync challenged } +type Handler handler + +func (h *Handler) BroadcastTransactions(txs types.Transactions) { + (*handler)(h).BroadcastTransactions(txs) +} + +func (h *Handler) PeerCount() int { + return h.peers.len() +} + +func (h *Handler) Start(maxPeers int) { + (*handler)(h).Start(maxPeers) +} + type handler struct { networkID uint64 forkFilter forkid.Filter // Fork ID filter, constant across the lifetime of the node @@ -104,7 +118,7 @@ type handler struct { database ethdb.Database txpool txPool - chain *core.BlockChain + chain eth.HandlerBlockchain maxPeers int downloader *downloader.Downloader diff --git a/eth/handler_eth.go b/eth/handler_eth.go index aed41c585912d..e15dea63f1663 100644 --- a/eth/handler_eth.go +++ b/eth/handler_eth.go @@ -23,20 +23,21 @@ import ( "time" "github.com/blockcypher/go-ethereum/common" - "github.com/blockcypher/go-ethereum/core" "github.com/blockcypher/go-ethereum/core/types" "github.com/blockcypher/go-ethereum/eth/protocols/eth" "github.com/blockcypher/go-ethereum/p2p/enode" "github.com/blockcypher/go-ethereum/trie" ) +type EthHandler ethHandler + // ethHandler implements the eth.Backend interface to handle the various network // packets that are sent as replies or broadcasts. type ethHandler handler -func (h *ethHandler) Chain() *core.BlockChain { return h.chain } -func (h *ethHandler) StateBloom() *trie.SyncBloom { return h.stateBloom } -func (h *ethHandler) TxPool() eth.TxPool { return h.txpool } +func (h *ethHandler) Chain() eth.HandlerBlockchain { return h.chain } +func (h *ethHandler) StateBloom() *trie.SyncBloom { return h.stateBloom } +func (h *ethHandler) TxPool() eth.TxPool { return h.txpool } // RunPeer is invoked when a peer joins on the `eth` protocol. func (h *ethHandler) RunPeer(peer *eth.Peer, hand eth.Handler) error { diff --git a/eth/handler_eth_test.go b/eth/handler_eth_test.go index 02fd472037ba6..9d435c453ebe4 100644 --- a/eth/handler_eth_test.go +++ b/eth/handler_eth_test.go @@ -49,7 +49,7 @@ type testEthHandler struct { txBroadcasts event.Feed } -func (h *testEthHandler) Chain() *core.BlockChain { panic("no backing chain") } +func (h *testEthHandler) Chain() eth.HandlerBlockchain { panic("no backing chain") } func (h *testEthHandler) StateBloom() *trie.SyncBloom { panic("no backing state bloom") } func (h *testEthHandler) TxPool() eth.TxPool { panic("no backing tx pool") } func (h *testEthHandler) AcceptTxs() bool { return true } diff --git a/eth/handler_snap.go b/eth/handler_snap.go index f9f2c299042a5..3e49f3beb2669 100644 --- a/eth/handler_snap.go +++ b/eth/handler_snap.go @@ -17,7 +17,7 @@ package eth import ( - "github.com/blockcypher/go-ethereum/core" + "github.com/blockcypher/go-ethereum/eth/protocols/eth" "github.com/blockcypher/go-ethereum/eth/protocols/snap" "github.com/blockcypher/go-ethereum/p2p/enode" ) @@ -26,7 +26,7 @@ import ( // packets that are sent as replies or broadcasts. type snapHandler handler -func (h *snapHandler) Chain() *core.BlockChain { return h.chain } +func (h *snapHandler) Chain() eth.HandlerBlockchain { return h.chain } // RunPeer is invoked when a peer joins on the `snap` protocol. func (h *snapHandler) RunPeer(peer *snap.Peer, hand snap.Handler) error { diff --git a/eth/protocols/eth/discovery.go b/eth/protocols/eth/discovery.go index 4fe067318562d..b8f225c4facfb 100644 --- a/eth/protocols/eth/discovery.go +++ b/eth/protocols/eth/discovery.go @@ -38,7 +38,7 @@ func (e enrEntry) ENRKey() string { // StartENRUpdater starts the `eth` ENR updater loop, which listens for chain // head events and updates the requested node record whenever a fork is passed. -func StartENRUpdater(chain *core.BlockChain, ln *enode.LocalNode) { +func StartENRUpdater(chain HandlerBlockchain, ln *enode.LocalNode) { var newHead = make(chan core.ChainHeadEvent, 10) sub := chain.SubscribeChainHeadEvent(newHead) @@ -58,7 +58,7 @@ func StartENRUpdater(chain *core.BlockChain, ln *enode.LocalNode) { } // currentENREntry constructs an `eth` ENR entry based on the current state of the chain. -func currentENREntry(chain *core.BlockChain) *enrEntry { +func currentENREntry(chain HandlerBlockchain) *enrEntry { return &enrEntry{ ForkID: forkid.NewID(chain.Config(), chain.Genesis().Hash(), chain.CurrentHeader().Number.Uint64()), } diff --git a/eth/protocols/eth/handler.go b/eth/protocols/eth/handler.go index fad7ab7ecbedc..9de5410c4678b 100644 --- a/eth/protocols/eth/handler.go +++ b/eth/protocols/eth/handler.go @@ -22,13 +22,18 @@ import ( "time" "github.com/blockcypher/go-ethereum/common" + "github.com/blockcypher/go-ethereum/consensus" "github.com/blockcypher/go-ethereum/core" + "github.com/blockcypher/go-ethereum/core/state" + "github.com/blockcypher/go-ethereum/core/state/snapshot" "github.com/blockcypher/go-ethereum/core/types" + "github.com/blockcypher/go-ethereum/event" "github.com/blockcypher/go-ethereum/metrics" "github.com/blockcypher/go-ethereum/p2p" "github.com/blockcypher/go-ethereum/p2p/enode" "github.com/blockcypher/go-ethereum/p2p/enr" "github.com/blockcypher/go-ethereum/params" + "github.com/blockcypher/go-ethereum/rlp" "github.com/blockcypher/go-ethereum/trie" ) @@ -59,6 +64,60 @@ const ( maxReceiptsServe = 1024 ) +type HandlerBlockchain interface { + SetHead(head uint64) error + CurrentBlock() *types.Block + CurrentFastBlock() *types.Block + Genesis() *types.Block + + HasBlock(hash common.Hash, number uint64) bool + HasFastBlock(hash common.Hash, number uint64) bool + GetBlock(hash common.Hash, number uint64) *types.Block + GetBlockByHash(hash common.Hash) *types.Block + StopInsert() + InsertBlockWithoutSetHead(block *types.Block) error + InsertReceiptChain(blockChain types.Blocks, receiptChain []types.Receipts, ancientLimit uint64) (int, error) + + SetTxLookupLimit(limit uint64) + TxLookupLimit() uint64 + + InsertChain(chain types.Blocks) (int, error) + + InsertHeaderChain(chain []*types.Header, checkFreq int) (int, error) + CurrentHeader() *types.Header + GetTd(hash common.Hash, number uint64) *big.Int + GetHeader(hash common.Hash, number uint64) *types.Header + GetHeaderByHash(hash common.Hash) *types.Header + HasHeader(hash common.Hash, number uint64) bool + GetHeaderByNumber(number uint64) *types.Header + + Config() *params.ChainConfig + Engine() consensus.Engine + + // Additionnal func for particular handler + // required by snap + SnapSyncCommitHead(common.Hash) error + Snapshots() *snapshot.Tree + ContractCode(hash common.Hash) ([]byte, error) + StateCache() state.Database + + // required by discovery.go + SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription + + // required by eth/handlers.go + GetAncestor(hash common.Hash, number, ancestor uint64, maxNonCanonical *uint64) (common.Hash, uint64) + GetBodyRLP(hash common.Hash) rlp.RawValue + TrieNode(hash common.Hash) ([]byte, error) + ContractCodeWithPrefix(hash common.Hash) ([]byte, error) + GetReceiptsByHash(hash common.Hash) types.Receipts + + // required for eth/handler_test.go + GetBlockByNumber(number uint64) *types.Block + GetCanonicalHash(number uint64) common.Hash + StateAt(root common.Hash) (*state.StateDB, error) + Stop() +} + // Handler is a callback to invoke from an outside runner after the boilerplate // exchanges have passed. type Handler func(peer *Peer) error @@ -67,7 +126,7 @@ type Handler func(peer *Peer) error // callback methods to invoke on remote deliveries. type Backend interface { // Chain retrieves the blockchain object to serve data. - Chain() *core.BlockChain + Chain() HandlerBlockchain // StateBloom retrieves the bloom filter - if any - for state trie nodes. StateBloom() *trie.SyncBloom @@ -142,7 +201,7 @@ type NodeInfo struct { } // nodeInfo retrieves some `eth` protocol metadata about the running host node. -func nodeInfo(chain *core.BlockChain, network uint64) *NodeInfo { +func nodeInfo(chain HandlerBlockchain, network uint64) *NodeInfo { head := chain.CurrentBlock() return &NodeInfo{ Network: network, diff --git a/eth/protocols/eth/handler_test.go b/eth/protocols/eth/handler_test.go index 156d5a5ef3ad6..cc53f6794215e 100644 --- a/eth/protocols/eth/handler_test.go +++ b/eth/protocols/eth/handler_test.go @@ -50,7 +50,7 @@ var ( // in the `eth` protocol without actually doing any data processing. type testBackend struct { db ethdb.Database - chain *core.BlockChain + chain HandlerBlockchain txpool *core.TxPool } @@ -91,7 +91,7 @@ func (b *testBackend) close() { b.chain.Stop() } -func (b *testBackend) Chain() *core.BlockChain { return b.chain } +func (b *testBackend) Chain() HandlerBlockchain { return b.chain } func (b *testBackend) StateBloom() *trie.SyncBloom { return nil } func (b *testBackend) TxPool() TxPool { return b.txpool } diff --git a/eth/protocols/eth/handlers.go b/eth/protocols/eth/handlers.go index 44d0509185d28..c47933bf490f0 100644 --- a/eth/protocols/eth/handlers.go +++ b/eth/protocols/eth/handlers.go @@ -21,7 +21,6 @@ import ( "fmt" "github.com/blockcypher/go-ethereum/common" - "github.com/blockcypher/go-ethereum/core" "github.com/blockcypher/go-ethereum/core/types" "github.com/blockcypher/go-ethereum/log" "github.com/blockcypher/go-ethereum/rlp" @@ -41,7 +40,7 @@ func handleGetBlockHeaders66(backend Backend, msg Decoder, peer *Peer) error { // ServiceGetBlockHeadersQuery assembles the response to a header query. It is // exposed to allow external packages to test protocol behavior. -func ServiceGetBlockHeadersQuery(chain *core.BlockChain, query *GetBlockHeadersPacket, peer *Peer) []*types.Header { +func ServiceGetBlockHeadersQuery(chain HandlerBlockchain, query *GetBlockHeadersPacket, peer *Peer) []*types.Header { hashMode := query.Origin.Hash != (common.Hash{}) first := true maxNonCanonical := uint64(100) @@ -139,7 +138,7 @@ func handleGetBlockBodies66(backend Backend, msg Decoder, peer *Peer) error { // ServiceGetBlockBodiesQuery assembles the response to a body query. It is // exposed to allow external packages to test protocol behavior. -func ServiceGetBlockBodiesQuery(chain *core.BlockChain, query GetBlockBodiesPacket) []rlp.RawValue { +func ServiceGetBlockBodiesQuery(chain HandlerBlockchain, query GetBlockBodiesPacket) []rlp.RawValue { // Gather blocks until the fetch or network limits is reached var ( bytes int @@ -170,7 +169,7 @@ func handleGetNodeData66(backend Backend, msg Decoder, peer *Peer) error { // ServiceGetNodeDataQuery assembles the response to a node data query. It is // exposed to allow external packages to test protocol behavior. -func ServiceGetNodeDataQuery(chain *core.BlockChain, bloom *trie.SyncBloom, query GetNodeDataPacket) [][]byte { +func ServiceGetNodeDataQuery(chain HandlerBlockchain, bloom *trie.SyncBloom, query GetNodeDataPacket) [][]byte { // Gather state data until the fetch or network limits is reached var ( bytes int @@ -211,7 +210,7 @@ func handleGetReceipts66(backend Backend, msg Decoder, peer *Peer) error { // ServiceGetReceiptsQuery assembles the response to a receipt query. It is // exposed to allow external packages to test protocol behavior. -func ServiceGetReceiptsQuery(chain *core.BlockChain, query GetReceiptsPacket) []rlp.RawValue { +func ServiceGetReceiptsQuery(chain HandlerBlockchain, query GetReceiptsPacket) []rlp.RawValue { // Gather state data until the fetch or network limits is reached var ( bytes int diff --git a/eth/protocols/snap/handler.go b/eth/protocols/snap/handler.go index 41e53fca2b4b8..eb50970525949 100644 --- a/eth/protocols/snap/handler.go +++ b/eth/protocols/snap/handler.go @@ -22,8 +22,8 @@ import ( "time" "github.com/blockcypher/go-ethereum/common" - "github.com/blockcypher/go-ethereum/core" "github.com/blockcypher/go-ethereum/core/types" + "github.com/blockcypher/go-ethereum/eth/protocols/eth" "github.com/blockcypher/go-ethereum/light" "github.com/blockcypher/go-ethereum/log" "github.com/blockcypher/go-ethereum/metrics" @@ -65,7 +65,7 @@ type Handler func(peer *Peer) error // callback methods to invoke on remote deliveries. type Backend interface { // Chain retrieves the blockchain object to serve data. - Chain() *core.BlockChain + Chain() eth.HandlerBlockchain // RunPeer is invoked when a peer joins on the `eth` protocol. The handler // should do any peer maintenance work, handshakes and validations. If all @@ -280,7 +280,7 @@ func handleMessage(backend Backend, peer *Peer) error { // ServiceGetAccountRangeQuery assembles the response to an account range query. // It is exposed to allow external packages to test protocol behavior. -func ServiceGetAccountRangeQuery(chain *core.BlockChain, req *GetAccountRangePacket) ([]*AccountData, [][]byte) { +func ServiceGetAccountRangeQuery(chain eth.HandlerBlockchain, req *GetAccountRangePacket) ([]*AccountData, [][]byte) { if req.Bytes > softResponseLimit { req.Bytes = softResponseLimit } @@ -337,7 +337,7 @@ func ServiceGetAccountRangeQuery(chain *core.BlockChain, req *GetAccountRangePac return accounts, proofs } -func ServiceGetStorageRangesQuery(chain *core.BlockChain, req *GetStorageRangesPacket) ([][]*StorageData, [][]byte) { +func ServiceGetStorageRangesQuery(chain eth.HandlerBlockchain, req *GetStorageRangesPacket) ([][]*StorageData, [][]byte) { if req.Bytes > softResponseLimit { req.Bytes = softResponseLimit } @@ -447,7 +447,7 @@ func ServiceGetStorageRangesQuery(chain *core.BlockChain, req *GetStorageRangesP // ServiceGetByteCodesQuery assembles the response to a byte codes query. // It is exposed to allow external packages to test protocol behavior. -func ServiceGetByteCodesQuery(chain *core.BlockChain, req *GetByteCodesPacket) [][]byte { +func ServiceGetByteCodesQuery(chain eth.HandlerBlockchain, req *GetByteCodesPacket) [][]byte { if req.Bytes > softResponseLimit { req.Bytes = softResponseLimit } @@ -477,7 +477,7 @@ func ServiceGetByteCodesQuery(chain *core.BlockChain, req *GetByteCodesPacket) [ // ServiceGetTrieNodesQuery assembles the response to a trie nodes query. // It is exposed to allow external packages to test protocol behavior. -func ServiceGetTrieNodesQuery(chain *core.BlockChain, req *GetTrieNodesPacket, start time.Time) ([][]byte, error) { +func ServiceGetTrieNodesQuery(chain eth.HandlerBlockchain, req *GetTrieNodesPacket, start time.Time) ([][]byte, error) { if req.Bytes > softResponseLimit { req.Bytes = softResponseLimit } @@ -559,6 +559,6 @@ func ServiceGetTrieNodesQuery(chain *core.BlockChain, req *GetTrieNodesPacket, s type NodeInfo struct{} // nodeInfo retrieves some `snap` protocol metadata about the running host node. -func nodeInfo(chain *core.BlockChain) *NodeInfo { +func nodeInfo(chain eth.HandlerBlockchain) *NodeInfo { return &NodeInfo{} }