// Copyright 2018 The go-ethereum Authors // This file is part of the go-ethereum library. // // The go-ethereum library is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // The go-ethereum library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . package les import ( "math/big" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/light" "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/params" ) // lesCommons contains fields needed by both server and client. type lesCommons struct { config *eth.Config iConfig *light.IndexerConfig chainDb ethdb.Database protocolManager *ProtocolManager chtIndexer, bloomTrieIndexer *core.ChainIndexer } // NodeInfo represents a short summary of the Ethereum sub-protocol metadata // known about the host peer. type NodeInfo struct { Network uint64 `json:"network"` // Ethereum network ID (1=Frontier, 2=Morden, Ropsten=3, Rinkeby=4) Difficulty *big.Int `json:"difficulty"` // Total difficulty of the host's blockchain Genesis common.Hash `json:"genesis"` // SHA3 hash of the host's genesis block Config *params.ChainConfig `json:"config"` // Chain configuration for the fork rules Head common.Hash `json:"head"` // SHA3 hash of the host's best owned block CHT params.TrustedCheckpoint `json:"cht"` // Trused CHT checkpoint for fast catchup } // makeProtocols creates protocol descriptors for the given LES versions. func (c *lesCommons) makeProtocols(versions []uint) []p2p.Protocol { protos := make([]p2p.Protocol, len(versions)) for i, version := range versions { version := version protos[i] = p2p.Protocol{ Name: "les", Version: version, Length: ProtocolLengths[version], NodeInfo: c.nodeInfo, Run: func(p *p2p.Peer, rw p2p.MsgReadWriter) error { return c.protocolManager.runPeer(version, p, rw) }, PeerInfo: func(id enode.ID) interface{} { if p := c.protocolManager.peers.Peer(peerIdToString(id)); p != nil { return p.Info() } return nil }, } } return protos } // nodeInfo retrieves some protocol metadata about the running host node. func (c *lesCommons) nodeInfo() interface{} { chain := c.protocolManager.blockchain head := chain.CurrentHeader() hash := head.Hash() return &NodeInfo{ Network: c.config.NetworkId, Difficulty: chain.GetTd(hash, head.Number.Uint64()), Genesis: chain.Genesis().Hash(), Config: chain.Config(), Head: chain.CurrentHeader().Hash(), CHT: c.latestLocalCheckpoint(), } } // latestLocalCheckpoint finds the common stored section index and returns a set of // post-processed trie roots (CHT and BloomTrie) associated with // the appropriate section index and head hash as a local checkpoint package. func (c *lesCommons) latestLocalCheckpoint() params.TrustedCheckpoint { sections, _, _ := c.chtIndexer.Sections() sections2, _, _ := c.bloomTrieIndexer.Sections() // Cap the section index if the two sections are not consistent. if sections > sections2 { sections = sections2 } if sections == 0 { // No checkpoint information can be provided. return params.TrustedCheckpoint{} } return c.getLocalCheckpoint(sections - 1) } // getLocalCheckpoint returns a set of post-processed trie roots (CHT and BloomTrie) // associated with the appropriate head hash by specific section index. // // The returned checkpoint is only the checkpoint generated by the local indexers, // not the stable checkpoint registered in the registrar contract. func (c *lesCommons) getLocalCheckpoint(index uint64) params.TrustedCheckpoint { sectionHead := c.chtIndexer.SectionHead(index) return params.TrustedCheckpoint{ SectionIndex: index, SectionHead: sectionHead, CHTRoot: light.GetChtRoot(c.chainDb, index, sectionHead), BloomRoot: light.GetBloomTrieRoot(c.chainDb, index, sectionHead), } }