github.com/neatlab/neatio@v1.7.3-0.20220425043230-d903e92fcc75/chain/consensus/neatcon/node.go (about)

     1  package neatcon
     2  
     3  import (
     4  	"io/ioutil"
     5  	"os"
     6  	"strings"
     7  
     8  	"github.com/neatlab/neatio/chain/consensus/neatcon/consensus"
     9  	"github.com/neatlab/neatio/chain/consensus/neatcon/epoch"
    10  	"github.com/neatlab/neatio/chain/consensus/neatcon/types"
    11  	"github.com/neatlab/neatio/chain/core"
    12  	"github.com/neatlab/neatio/chain/log"
    13  	"github.com/neatlab/neatio/params"
    14  	cmn "github.com/neatlib/common-go"
    15  	cfg "github.com/neatlib/config-go"
    16  	dbm "github.com/neatlib/db-go"
    17  )
    18  
    19  type Node struct {
    20  	cmn.BaseService
    21  
    22  	privValidator *types.PrivValidator
    23  
    24  	epochDB dbm.DB
    25  
    26  	evsw             types.EventSwitch
    27  	consensusState   *consensus.ConsensusState
    28  	consensusReactor *consensus.ConsensusReactor
    29  
    30  	cch    core.CrossChainHelper
    31  	logger log.Logger
    32  }
    33  
    34  func NewNodeNotStart(backend *backend, config cfg.Config, chainConfig *params.ChainConfig, cch core.CrossChainHelper, genDoc *types.GenesisDoc) *Node {
    35  	var privValidator *types.PrivValidator
    36  	privValidatorFile := config.GetString("priv_validator_file")
    37  	if _, err := os.Stat(privValidatorFile); err == nil {
    38  		privValidator = types.LoadPrivValidator(privValidatorFile)
    39  	}
    40  
    41  	epochDB := dbm.NewDB("epoch", "leveldb", config.GetString("db_dir"))
    42  	ep := epoch.InitEpoch(epochDB, genDoc, backend.logger)
    43  
    44  	if privValidator != nil && ep.Validators.HasAddress(privValidator.Address[:]) {
    45  		backend.shouldStart = true
    46  	} else {
    47  		backend.shouldStart = false
    48  	}
    49  
    50  	consensusState := consensus.NewConsensusState(backend, config, chainConfig, cch, ep)
    51  	if privValidator != nil {
    52  		consensusState.SetPrivValidator(privValidator)
    53  	}
    54  	consensusReactor := consensus.NewConsensusReactor(consensusState)
    55  
    56  	eventSwitch := types.NewEventSwitch()
    57  	SetEventSwitch(eventSwitch, consensusReactor)
    58  
    59  	node := &Node{
    60  		privValidator: privValidator,
    61  
    62  		epochDB: epochDB,
    63  
    64  		evsw: eventSwitch,
    65  
    66  		cch: cch,
    67  
    68  		consensusState:   consensusState,
    69  		consensusReactor: consensusReactor,
    70  
    71  		logger: backend.logger,
    72  	}
    73  	node.BaseService = *cmn.NewBaseService(backend.logger, "Node", node)
    74  
    75  	return node
    76  }
    77  
    78  func (n *Node) OnStart() error {
    79  
    80  	n.logger.Info("(n *Node) OnStart()")
    81  
    82  	if n.privValidator == nil {
    83  		return ErrNoPrivValidator
    84  	}
    85  
    86  	_, err := n.evsw.Start()
    87  	if err != nil {
    88  		n.logger.Errorf("Failed to start switch: %v", err)
    89  		return err
    90  	}
    91  
    92  	_, err = n.consensusReactor.Start()
    93  	if err != nil {
    94  		n.evsw.Stop()
    95  		n.logger.Errorf("Failed to start Consensus Reactor. Error: %v", err)
    96  		return err
    97  	}
    98  
    99  	return nil
   100  }
   101  
   102  func (n *Node) OnStop() {
   103  	n.logger.Info("(n *Node) OnStop() called")
   104  	n.BaseService.OnStop()
   105  
   106  	n.evsw.Stop()
   107  	n.consensusReactor.Stop()
   108  }
   109  
   110  func (n *Node) RunForever() {
   111  	cmn.TrapSignal(func() {
   112  		n.Stop()
   113  	})
   114  }
   115  
   116  func SetEventSwitch(evsw types.EventSwitch, eventables ...types.Eventable) {
   117  	for _, e := range eventables {
   118  		e.SetEventSwitch(evsw)
   119  	}
   120  }
   121  
   122  func (n *Node) ConsensusState() *consensus.ConsensusState {
   123  	return n.consensusState
   124  }
   125  
   126  func (n *Node) ConsensusReactor() *consensus.ConsensusReactor {
   127  	return n.consensusReactor
   128  }
   129  
   130  func (n *Node) EventSwitch() types.EventSwitch {
   131  	return n.evsw
   132  }
   133  
   134  func (n *Node) PrivValidator() *types.PrivValidator {
   135  	return n.privValidator
   136  }
   137  
   138  func ProtocolAndAddress(listenAddr string) (string, string) {
   139  	protocol, address := "tcp", listenAddr
   140  	parts := strings.SplitN(address, "://", 2)
   141  	if len(parts) == 2 {
   142  		protocol, address = parts[0], parts[1]
   143  	}
   144  	return protocol, address
   145  }
   146  
   147  func MakeNeatConNode(backend *backend, config cfg.Config, chainConfig *params.ChainConfig, cch core.CrossChainHelper) *Node {
   148  
   149  	var genDoc *types.GenesisDoc
   150  	genDocFile := config.GetString("genesis_file")
   151  
   152  	if !cmn.FileExists(genDocFile) {
   153  		if chainConfig.NeatChainId == params.MainnetChainConfig.NeatChainId {
   154  			genDoc, _ = types.GenesisDocFromJSON([]byte(types.MainnetGenesisJSON))
   155  		} else if chainConfig.NeatChainId == params.TestnetChainConfig.NeatChainId {
   156  			genDoc, _ = types.GenesisDocFromJSON([]byte(types.TestnetGenesisJSON))
   157  		} else {
   158  			return nil
   159  		}
   160  	} else {
   161  		genDoc = readGenesisFromFile(genDocFile)
   162  	}
   163  	config.Set("chain_id", genDoc.ChainID)
   164  
   165  	return NewNodeNotStart(backend, config, chainConfig, cch, genDoc)
   166  }
   167  
   168  func readGenesisFromFile(genDocFile string) *types.GenesisDoc {
   169  	jsonBlob, err := ioutil.ReadFile(genDocFile)
   170  	if err != nil {
   171  		cmn.Exit(cmn.Fmt("Couldn't read GenesisDoc file: %v", err))
   172  	}
   173  	genDoc, err := types.GenesisDocFromJSON(jsonBlob)
   174  	if err != nil {
   175  		cmn.PanicSanity(cmn.Fmt("Genesis doc parse json error: %v", err))
   176  	}
   177  	if genDoc.ChainID == "" {
   178  		cmn.PanicSanity(cmn.Fmt("Genesis doc %v must include non-empty chain_id", genDocFile))
   179  	}
   180  	return genDoc
   181  }