github.com/ebakus/go-ebakus@v1.0.5-0.20200520105415-dbccef9ec421/les/commons.go (about) 1 // Copyright 2019 The ebakus/go-ebakus Authors 2 // This file is part of the ebakus/go-ebakus library. 3 // 4 // The ebakus/go-ebakus library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The ebakus/go-ebakus library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the ebakus/go-ebakus library. If not, see <http://www.gnu.org/licenses/>. 16 17 package les 18 19 import ( 20 "fmt" 21 "math/big" 22 "sync" 23 24 "github.com/ebakus/go-ebakus/common" 25 "github.com/ebakus/go-ebakus/core" 26 "github.com/ebakus/go-ebakus/core/types" 27 "github.com/ebakus/go-ebakus/eth" 28 "github.com/ebakus/go-ebakus/ethdb" 29 "github.com/ebakus/go-ebakus/light" 30 "github.com/ebakus/go-ebakus/p2p" 31 "github.com/ebakus/go-ebakus/p2p/discv5" 32 "github.com/ebakus/go-ebakus/p2p/enode" 33 "github.com/ebakus/go-ebakus/params" 34 ) 35 36 func errResp(code errCode, format string, v ...interface{}) error { 37 return fmt.Errorf("%v - %v", code, fmt.Sprintf(format, v...)) 38 } 39 40 func lesTopic(genesisHash common.Hash, protocolVersion uint) discv5.Topic { 41 var name string 42 switch protocolVersion { 43 case lpv2: 44 name = "LES2" 45 default: 46 panic(nil) 47 } 48 return discv5.Topic(name + "@" + common.Bytes2Hex(genesisHash.Bytes()[0:8])) 49 } 50 51 type chainReader interface { 52 CurrentHeader() *types.Header 53 } 54 55 // lesCommons contains fields needed by both server and client. 56 type lesCommons struct { 57 genesis common.Hash 58 config *eth.Config 59 chainConfig *params.ChainConfig 60 iConfig *light.IndexerConfig 61 chainDb ethdb.Database 62 peers *peerSet 63 chainReader chainReader 64 chtIndexer, bloomTrieIndexer *core.ChainIndexer 65 oracle *checkpointOracle 66 67 closeCh chan struct{} 68 wg sync.WaitGroup 69 } 70 71 // NodeInfo represents a short summary of the Ebakus sub-protocol metadata 72 // known about the host peer. 73 type NodeInfo struct { 74 Network uint64 `json:"network"` // Ebakus network ID (1=Frontier, 2=Morden, Ropsten=3, Rinkeby=4) 75 HeadNumber *big.Int `json:"difficulty"` // Head number of the host's blockchain 76 Genesis common.Hash `json:"genesis"` // SHA3 hash of the host's genesis block 77 Config *params.ChainConfig `json:"config"` // Chain configuration for the fork rules 78 Head common.Hash `json:"head"` // SHA3 hash of the host's best owned block 79 CHT params.TrustedCheckpoint `json:"cht"` // Trused CHT checkpoint for fast catchup 80 } 81 82 // makeProtocols creates protocol descriptors for the given LES versions. 83 func (c *lesCommons) makeProtocols(versions []uint, runPeer func(version uint, p *p2p.Peer, rw p2p.MsgReadWriter) error, peerInfo func(id enode.ID) interface{}) []p2p.Protocol { 84 protos := make([]p2p.Protocol, len(versions)) 85 for i, version := range versions { 86 version := version 87 protos[i] = p2p.Protocol{ 88 Name: "les", 89 Version: version, 90 Length: ProtocolLengths[version], 91 NodeInfo: c.nodeInfo, 92 Run: func(peer *p2p.Peer, rw p2p.MsgReadWriter) error { 93 return runPeer(version, peer, rw) 94 }, 95 PeerInfo: peerInfo, 96 } 97 } 98 return protos 99 } 100 101 // nodeInfo retrieves some protocol metadata about the running host node. 102 func (c *lesCommons) nodeInfo() interface{} { 103 head := c.chainReader.CurrentHeader() 104 hash := head.Hash() 105 return &NodeInfo{ 106 Network: c.config.NetworkId, 107 Genesis: c.genesis, 108 Config: c.chainConfig, 109 Head: hash, 110 CHT: c.latestLocalCheckpoint(), 111 } 112 } 113 114 // latestLocalCheckpoint finds the common stored section index and returns a set 115 // of post-processed trie roots (CHT and BloomTrie) associated with the appropriate 116 // section index and head hash as a local checkpoint package. 117 func (c *lesCommons) latestLocalCheckpoint() params.TrustedCheckpoint { 118 sections, _, _ := c.chtIndexer.Sections() 119 sections2, _, _ := c.bloomTrieIndexer.Sections() 120 // Cap the section index if the two sections are not consistent. 121 if sections > sections2 { 122 sections = sections2 123 } 124 if sections == 0 { 125 // No checkpoint information can be provided. 126 return params.TrustedCheckpoint{} 127 } 128 return c.localCheckpoint(sections - 1) 129 } 130 131 // localCheckpoint returns a set of post-processed trie roots (CHT and BloomTrie) 132 // associated with the appropriate head hash by specific section index. 133 // 134 // The returned checkpoint is only the checkpoint generated by the local indexers, 135 // not the stable checkpoint registered in the registrar contract. 136 func (c *lesCommons) localCheckpoint(index uint64) params.TrustedCheckpoint { 137 sectionHead := c.chtIndexer.SectionHead(index) 138 return params.TrustedCheckpoint{ 139 SectionIndex: index, 140 SectionHead: sectionHead, 141 CHTRoot: light.GetChtRoot(c.chainDb, index, sectionHead), 142 BloomRoot: light.GetBloomTrieRoot(c.chainDb, index, sectionHead), 143 } 144 }