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 }