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  }