github.com/klaytn/klaytn@v1.12.1/node/sc/mainbridge.go (about)

     1  // Modifications Copyright 2019 The klaytn Authors
     2  // Copyright 2014 The go-ethereum Authors
     3  // This file is part of go-ethereum.
     4  //
     5  // The go-ethereum library is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU Lesser General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // The go-ethereum library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    13  // GNU Lesser General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Lesser General Public License
    16  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    17  //
    18  // This file is derived from eth/backend.go (2018/06/04).
    19  // Modified and improved for the klaytn development.
    20  
    21  package sc
    22  
    23  import (
    24  	"errors"
    25  	"fmt"
    26  	"io"
    27  	"math/big"
    28  	"net"
    29  	"sync"
    30  	"time"
    31  
    32  	"github.com/klaytn/klaytn/accounts"
    33  	"github.com/klaytn/klaytn/api"
    34  	"github.com/klaytn/klaytn/blockchain"
    35  	"github.com/klaytn/klaytn/blockchain/types"
    36  	"github.com/klaytn/klaytn/common"
    37  	"github.com/klaytn/klaytn/crypto"
    38  	"github.com/klaytn/klaytn/event"
    39  	"github.com/klaytn/klaytn/networks/p2p"
    40  	"github.com/klaytn/klaytn/networks/p2p/discover"
    41  	"github.com/klaytn/klaytn/networks/rpc"
    42  	"github.com/klaytn/klaytn/node"
    43  	"github.com/klaytn/klaytn/params"
    44  	"github.com/klaytn/klaytn/storage/database"
    45  )
    46  
    47  const (
    48  	// chainEventChanSize is the size of channel listening to ChainHeadEvent.
    49  	chainEventChanSize  = 10000
    50  	chainLogChanSize    = 10000
    51  	transactionChanSize = 10000
    52  	rpcBufferSize       = 1024
    53  )
    54  
    55  // MainBridgeInfo represents a short summary of the Klaytn sub-protocol metadata
    56  // known about the host peer.
    57  type MainBridgeInfo struct {
    58  	Network    uint64              `json:"network"`    // Klaytn network ID
    59  	BlockScore *big.Int            `json:"blockscore"` // Total blockscore of the host's blockchain
    60  	Genesis    common.Hash         `json:"genesis"`    // SHA3 hash of the host's genesis block
    61  	Config     *params.ChainConfig `json:"config"`     // Chain configuration for the fork rules
    62  	Head       common.Hash         `json:"head"`       // SHA3 hash of the host's best owned block
    63  }
    64  
    65  // MainBridge implements the main bridge of service chain.
    66  type MainBridge struct {
    67  	config *SCConfig
    68  
    69  	// DB interfaces
    70  	chainDB database.DBManager // Blockchain database
    71  
    72  	eventMux       *event.TypeMux
    73  	accountManager *accounts.Manager
    74  
    75  	networkId     uint64
    76  	netRPCService *api.PublicNetAPI
    77  
    78  	lock sync.RWMutex // Protects the variadic fields (e.g. gas price)
    79  
    80  	bridgeServer p2p.Server
    81  	ctx          *node.ServiceContext
    82  	maxPeers     int
    83  
    84  	APIBackend *MainBridgeAPI
    85  
    86  	// channels for fetcher, syncer, txsyncLoop
    87  	newPeerCh   chan BridgePeer
    88  	quitSync    chan struct{}
    89  	noMorePeers chan struct{}
    90  
    91  	// wait group is used for graceful shutdowns during downloading
    92  	// and processing
    93  	wg   sync.WaitGroup
    94  	pmwg sync.WaitGroup
    95  
    96  	blockchain *blockchain.BlockChain
    97  	txPool     *blockchain.TxPool
    98  
    99  	chainHeadCh  chan blockchain.ChainHeadEvent
   100  	chainHeadSub event.Subscription
   101  	logsCh       chan []*types.Log
   102  	logsSub      event.Subscription
   103  	txCh         chan blockchain.NewTxsEvent
   104  	txSub        event.Subscription
   105  
   106  	peers        *bridgePeerSet
   107  	handler      *MainBridgeHandler
   108  	eventhandler *MainChainEventHandler
   109  
   110  	rpcServer     *rpc.Server
   111  	rpcConn       net.Conn
   112  	rpcResponseCh chan []byte
   113  }
   114  
   115  // NewMainBridge creates a new MainBridge object (including the
   116  // initialisation of the common MainBridge object)
   117  func NewMainBridge(ctx *node.ServiceContext, config *SCConfig) (*MainBridge, error) {
   118  	chainDB := CreateDB(ctx, config, "scchaindata")
   119  
   120  	mb := &MainBridge{
   121  		config:         config,
   122  		chainDB:        chainDB,
   123  		peers:          newBridgePeerSet(),
   124  		newPeerCh:      make(chan BridgePeer),
   125  		noMorePeers:    make(chan struct{}),
   126  		eventMux:       ctx.EventMux,
   127  		accountManager: ctx.AccountManager,
   128  		networkId:      config.NetworkId,
   129  		ctx:            ctx,
   130  		chainHeadCh:    make(chan blockchain.ChainHeadEvent, chainEventChanSize),
   131  		logsCh:         make(chan []*types.Log, chainLogChanSize),
   132  		txCh:           make(chan blockchain.NewTxsEvent, transactionChanSize),
   133  		quitSync:       make(chan struct{}),
   134  		maxPeers:       config.MaxPeer,
   135  		rpcResponseCh:  make(chan []byte),
   136  	}
   137  
   138  	logger.Info("Initialising Klaytn-Bridge protocol", "network", config.NetworkId)
   139  	mb.APIBackend = &MainBridgeAPI{mb}
   140  
   141  	var err error
   142  	mb.handler, err = NewMainBridgeHandler(mb.config, mb)
   143  	if err != nil {
   144  		return nil, err
   145  	}
   146  	mb.eventhandler, err = NewMainChainEventHandler(mb, mb.handler)
   147  	if err != nil {
   148  		return nil, err
   149  	}
   150  
   151  	mb.rpcServer = rpc.NewServer()
   152  	p1, p2 := net.Pipe()
   153  	mb.rpcConn = p1
   154  	go mb.rpcServer.ServeCodec(rpc.NewCodec(p2), 0)
   155  
   156  	go func() {
   157  		for {
   158  			data := make([]byte, rpcBufferSize)
   159  			rlen, err := mb.rpcConn.Read(data)
   160  			if err != nil {
   161  				if err == io.EOF {
   162  					logger.Trace("EOF from the rpc server pipe")
   163  					time.Sleep(100 * time.Millisecond)
   164  					continue
   165  				} else {
   166  					// If no one closes the pipe, this situation should not happen.
   167  					logger.Error("failed to read from the rpc pipe", "err", err, "rlen", rlen)
   168  					return
   169  				}
   170  			}
   171  			logger.Trace("mainbridge message from rpc server pipe", "rlen", rlen)
   172  			err = mb.SendRPCResponseData(data[:rlen])
   173  			if err != nil {
   174  				logger.Error("failed to send response data from RPC server pipe", err)
   175  			}
   176  		}
   177  	}()
   178  
   179  	return mb, nil
   180  }
   181  
   182  // CreateDB creates the chain database.
   183  func CreateDB(ctx *node.ServiceContext, config *SCConfig, name string) database.DBManager {
   184  	// OpenFilesLimit and LevelDBCacheSize are used by minimum value.
   185  	dbc := &database.DBConfig{Dir: name, DBType: database.LevelDB}
   186  	return ctx.OpenDatabase(dbc)
   187  }
   188  
   189  // BridgePeerSet implements PeerSetManager
   190  func (mb *MainBridge) BridgePeerSet() *bridgePeerSet {
   191  	return mb.peers
   192  }
   193  
   194  // APIs returns the collection of RPC services the Klaytn sc package offers.
   195  // NOTE, some of these services probably need to be moved to somewhere else.
   196  func (mb *MainBridge) APIs() []rpc.API {
   197  	// Append all the local APIs and return
   198  	return []rpc.API{
   199  		{
   200  			Namespace: "mainbridge",
   201  			Version:   "1.0",
   202  			Service:   mb.APIBackend,
   203  			Public:    true,
   204  		},
   205  		{
   206  			Namespace: "mainbridge",
   207  			Version:   "1.0",
   208  			Service:   mb.netRPCService,
   209  			Public:    true,
   210  		},
   211  	}
   212  }
   213  
   214  func (mb *MainBridge) AccountManager() *accounts.Manager { return mb.accountManager }
   215  func (mb *MainBridge) EventMux() *event.TypeMux          { return mb.eventMux }
   216  func (mb *MainBridge) ChainDB() database.DBManager       { return mb.chainDB }
   217  func (mb *MainBridge) IsListening() bool                 { return true } // Always listening
   218  func (mb *MainBridge) ProtocolVersion() int              { return int(mb.SCProtocol().Versions[0]) }
   219  func (mb *MainBridge) NetVersion() uint64                { return mb.networkId }
   220  
   221  func (mb *MainBridge) Components() []interface{} {
   222  	return nil
   223  }
   224  
   225  func (mb *MainBridge) SetComponents(components []interface{}) {
   226  	for _, component := range components {
   227  		switch v := component.(type) {
   228  		case *blockchain.BlockChain:
   229  			mb.blockchain = v
   230  			// event from core-service
   231  			mb.chainHeadSub = mb.blockchain.SubscribeChainHeadEvent(mb.chainHeadCh)
   232  			mb.logsSub = mb.blockchain.SubscribeLogsEvent(mb.logsCh)
   233  		case *blockchain.TxPool:
   234  			mb.txPool = v
   235  			// event from core-service
   236  			mb.txSub = mb.txPool.SubscribeNewTxsEvent(mb.txCh)
   237  		case []rpc.API:
   238  			logger.Debug("p2p rpc registered", "len(v)", len(v))
   239  			for _, api := range v {
   240  				if api.Public && api.Namespace == "klay" {
   241  					logger.Error("p2p rpc registered", "namespace", api.Namespace)
   242  					if err := mb.rpcServer.RegisterName(api.Namespace, api.Service); err != nil {
   243  						logger.Error("pRPC failed to register", "namespace", api.Namespace)
   244  					}
   245  				}
   246  			}
   247  		}
   248  	}
   249  
   250  	mb.pmwg.Add(1)
   251  	go mb.loop()
   252  }
   253  
   254  // Protocols implements node.Service, returning all the currently configured
   255  // network protocols to start.
   256  func (mb *MainBridge) Protocols() []p2p.Protocol {
   257  	return []p2p.Protocol{}
   258  }
   259  
   260  func (mb *MainBridge) SCProtocol() SCProtocol {
   261  	return SCProtocol{
   262  		Name:     SCProtocolName,
   263  		Versions: SCProtocolVersion,
   264  		Lengths:  SCProtocolLength,
   265  	}
   266  }
   267  
   268  // NodeInfo retrieves some protocol metadata about the running host node.
   269  func (mb *MainBridge) NodeInfo() *MainBridgeInfo {
   270  	currentBlock := mb.blockchain.CurrentBlock()
   271  	return &MainBridgeInfo{
   272  		Network:    mb.networkId,
   273  		BlockScore: mb.blockchain.GetTd(currentBlock.Hash(), currentBlock.NumberU64()),
   274  		Genesis:    mb.blockchain.Genesis().Hash(),
   275  		Config:     mb.blockchain.Config(),
   276  		Head:       currentBlock.Hash(),
   277  	}
   278  }
   279  
   280  // getChainID returns the current chain id.
   281  func (mb *MainBridge) getChainID() *big.Int {
   282  	return mb.blockchain.Config().ChainID
   283  }
   284  
   285  // Start implements node.Service, starting all internal goroutines needed by the
   286  // Klaytn protocol implementation.
   287  func (mb *MainBridge) Start(srvr p2p.Server) error {
   288  	serverConfig := p2p.Config{}
   289  	serverConfig.PrivateKey = mb.ctx.NodeKey()
   290  	serverConfig.Name = mb.ctx.NodeType().String()
   291  	serverConfig.Logger = logger
   292  	serverConfig.ListenAddr = mb.config.MainBridgePort
   293  	serverConfig.MaxPhysicalConnections = mb.maxPeers
   294  	serverConfig.NoDiscovery = true
   295  	serverConfig.EnableMultiChannelServer = false
   296  	serverConfig.NoDial = true
   297  
   298  	scprotocols := make([]p2p.Protocol, 0, len(mb.SCProtocol().Versions))
   299  	for i, version := range mb.SCProtocol().Versions {
   300  		// Compatible; initialise the sub-protocol
   301  		version := version
   302  		scprotocols = append(scprotocols, p2p.Protocol{
   303  			Name:    mb.SCProtocol().Name,
   304  			Version: version,
   305  			Length:  mb.SCProtocol().Lengths[i],
   306  			Run: func(p *p2p.Peer, rw p2p.MsgReadWriter) error {
   307  				peer := mb.newPeer(int(version), p, rw)
   308  				pubKey, _ := p.ID().Pubkey()
   309  				addr := crypto.PubkeyToAddress(*pubKey)
   310  				peer.SetAddr(addr)
   311  				select {
   312  				case mb.newPeerCh <- peer:
   313  					mb.wg.Add(1)
   314  					defer mb.wg.Done()
   315  					return mb.handle(peer)
   316  				case <-mb.quitSync:
   317  					return p2p.DiscQuitting
   318  				}
   319  			},
   320  			NodeInfo: func() interface{} {
   321  				return mb.NodeInfo()
   322  			},
   323  			PeerInfo: func(id discover.NodeID) interface{} {
   324  				if p := mb.peers.Peer(fmt.Sprintf("%x", id[:8])); p != nil {
   325  					return p.Info()
   326  				}
   327  				return nil
   328  			},
   329  		})
   330  	}
   331  	mb.bridgeServer = p2p.NewServer(serverConfig)
   332  	mb.bridgeServer.AddProtocols(scprotocols)
   333  
   334  	if err := mb.bridgeServer.Start(); err != nil {
   335  		return errors.New("fail to bridgeserver start")
   336  	}
   337  
   338  	// Start the RPC service
   339  	mb.netRPCService = api.NewPublicNetAPI(mb.bridgeServer, mb.NetVersion())
   340  
   341  	// Figure out a max peers count based on the server limits
   342  	// s.maxPeers = s.bridgeServer.MaxPhysicalConnections()
   343  
   344  	go mb.syncer()
   345  
   346  	return nil
   347  }
   348  
   349  func (mb *MainBridge) newPeer(pv int, p *p2p.Peer, rw p2p.MsgReadWriter) BridgePeer {
   350  	return newBridgePeer(pv, p, newMeteredMsgWriter(rw))
   351  }
   352  
   353  func (mb *MainBridge) handle(p BridgePeer) error {
   354  	// Ignore maxPeers if this is a trusted peer
   355  	if mb.peers.Len() >= mb.maxPeers && !p.GetP2PPeer().Info().Networks[p2p.ConnDefault].Trusted {
   356  		return p2p.DiscTooManyPeers
   357  	}
   358  	p.GetP2PPeer().Log().Debug("Klaytn peer connected", "name", p.GetP2PPeer().Name())
   359  
   360  	// Execute the handshake
   361  	var (
   362  		head   = mb.blockchain.CurrentHeader()
   363  		hash   = head.Hash()
   364  		number = head.Number.Uint64()
   365  		td     = mb.blockchain.GetTd(hash, number)
   366  	)
   367  
   368  	err := p.Handshake(mb.networkId, mb.getChainID(), td, hash)
   369  	if err != nil {
   370  		p.GetP2PPeer().Log().Debug("Klaytn peer handshake failed", "err", err)
   371  		return err
   372  	}
   373  
   374  	// Register the peer locally
   375  	if err := mb.peers.Register(p); err != nil {
   376  		// if starting node with unlock account, can't register peer until finish unlock
   377  		p.GetP2PPeer().Log().Info("Klaytn peer registration failed", "err", err)
   378  		return err
   379  	}
   380  	defer mb.removePeer(p.GetID())
   381  
   382  	p.GetP2PPeer().Log().Info("Added a P2P Peer", "peerID", p.GetP2PPeerID())
   383  
   384  	// main loop. handle incoming messages.
   385  	for {
   386  		if err := mb.handleMsg(p); err != nil {
   387  			p.GetP2PPeer().Log().Debug("Klaytn message handling failed", "err", err)
   388  			return err
   389  		}
   390  	}
   391  }
   392  
   393  func (mb *MainBridge) SendRPCResponseData(data []byte) error {
   394  	peers := mb.BridgePeerSet().peers
   395  	logger.Trace("mainbridge send rpc response data to peers", "data len", len(data), "peers", len(peers))
   396  	for _, peer := range peers {
   397  		err := peer.SendResponseRPC(data)
   398  		if err != nil {
   399  			logger.Error("failed to send rpc response to the peer", "err", err)
   400  		}
   401  		return err
   402  	}
   403  
   404  	return nil
   405  }
   406  
   407  func (mb *MainBridge) loop() {
   408  	defer mb.pmwg.Done()
   409  
   410  	report := time.NewTicker(1 * time.Second)
   411  	defer report.Stop()
   412  
   413  	// Keep waiting for and reacting to the various events
   414  	for {
   415  		select {
   416  		// Handle ChainHeadEvent
   417  		case ev := <-mb.chainHeadCh:
   418  			if ev.Block != nil {
   419  				mb.eventhandler.HandleChainHeadEvent(ev.Block)
   420  			} else {
   421  				logger.Error("mainbridge block event is nil")
   422  			}
   423  		// Handle NewTxsEvent
   424  		case ev := <-mb.txCh:
   425  			if ev.Txs != nil {
   426  				mb.eventhandler.HandleTxsEvent(ev.Txs)
   427  			} else {
   428  				logger.Error("mainbridge tx event is nil")
   429  			}
   430  		// Handle ChainLogsEvent
   431  		case logs := <-mb.logsCh:
   432  			mb.eventhandler.HandleLogsEvent(logs)
   433  		case <-report.C:
   434  			// report status
   435  		case err := <-mb.chainHeadSub.Err():
   436  			if err != nil {
   437  				logger.Error("mainbridge block subscription ", "err", err)
   438  			}
   439  			return
   440  		case err := <-mb.txSub.Err():
   441  			if err != nil {
   442  				logger.Error("mainbridge tx subscription ", "err", err)
   443  			}
   444  			return
   445  		case err := <-mb.logsSub.Err():
   446  			if err != nil {
   447  				logger.Error("mainbridge log subscription ", "err", err)
   448  			}
   449  			return
   450  		}
   451  	}
   452  }
   453  
   454  func (mb *MainBridge) removePeer(id string) {
   455  	// Short circuit if the peer was already removed
   456  	peer := mb.peers.Peer(id)
   457  	if peer == nil {
   458  		return
   459  	}
   460  	logger.Debug("Removing Klaytn peer", "peer", id)
   461  
   462  	if err := mb.peers.Unregister(id); err != nil {
   463  		logger.Error("Peer removal failed", "peer", id, "err", err)
   464  	}
   465  	// Hard disconnect at the networking layer
   466  	if peer != nil {
   467  		peer.GetP2PPeer().Disconnect(p2p.DiscUselessPeer)
   468  	}
   469  }
   470  
   471  // handleMsg is invoked whenever an inbound message is received from a remote
   472  // peer. The remote connection is torn down upon returning any error.
   473  func (mb *MainBridge) handleMsg(p BridgePeer) error {
   474  	// Below message size checking is done by handle().
   475  	// Read the next message from the remote peer, and ensure it's fully consumed
   476  	msg, err := p.GetRW().ReadMsg()
   477  	if err != nil {
   478  		p.GetP2PPeer().Log().Warn("ProtocolManager failed to read msg", "err", err)
   479  		return err
   480  	}
   481  	if msg.Size > ProtocolMaxMsgSize {
   482  		err := errResp(ErrMsgTooLarge, "%v > %v", msg.Size, ProtocolMaxMsgSize)
   483  		p.GetP2PPeer().Log().Warn("ProtocolManager over max msg size", "err", err)
   484  		return err
   485  	}
   486  	defer msg.Discard()
   487  
   488  	return mb.handler.HandleSubMsg(p, msg)
   489  }
   490  
   491  func (mb *MainBridge) syncer() {
   492  	// Start and ensure cleanup of sync mechanisms
   493  	// pm.fetcher.Start()
   494  	// defer pm.fetcher.Stop()
   495  	// defer pm.downloader.Terminate()
   496  
   497  	// Wait for different events to fire synchronisation operations
   498  	forceSync := time.NewTicker(forceSyncCycle)
   499  	defer forceSync.Stop()
   500  
   501  	for {
   502  		select {
   503  		case peer := <-mb.newPeerCh:
   504  			go mb.synchronise(peer)
   505  
   506  		case <-forceSync.C:
   507  			// Force a sync even if not enough peers are present
   508  			go mb.synchronise(mb.peers.BestPeer())
   509  
   510  		case <-mb.noMorePeers:
   511  			return
   512  		}
   513  	}
   514  }
   515  
   516  func (mb *MainBridge) synchronise(peer BridgePeer) {
   517  	// @TODO Klaytn ServiceChain Sync
   518  }
   519  
   520  // Stop implements node.Service, terminating all internal goroutines used by the
   521  // Klaytn protocol.
   522  func (mb *MainBridge) Stop() error {
   523  	close(mb.quitSync)
   524  
   525  	mb.chainHeadSub.Unsubscribe()
   526  	mb.txSub.Unsubscribe()
   527  	mb.logsSub.Unsubscribe()
   528  	mb.eventMux.Stop()
   529  	mb.chainDB.Close()
   530  
   531  	mb.bridgeServer.Stop()
   532  
   533  	return nil
   534  }
   535  
   536  func errResp(code errCode, format string, v ...interface{}) error {
   537  	return fmt.Errorf("%v - %v", code, fmt.Sprintf(format, v...))
   538  }