예제 #1
0
def main(args):
    try:
        path_config = load_path_config(config_dir=args['config_dir'])
    except LocalConfigurationError as local_config_err:
        LOGGER.error(str(local_config_err))
        sys.exit(1)

    try:
        opts_config = ValidatorConfig(
            bind_component=args['bind_component'],
            bind_network=args['bind_network'],
            endpoint=args['endpoint'],
            maximum_peer_connectivity=args['maximum_peer_connectivity'],
            minimum_peer_connectivity=args['minimum_peer_connectivity'],
            roles=args['roles'],
            opentsdb_db=args['opentsdb_db'],
            opentsdb_url=args['opentsdb_url'],
            peering=args['peering'],
            peers=args['peers'],
            scheduler=args['scheduler'],
            seeds=args['seeds'],
        )

        validator_config = \
            load_validator_config(opts_config, path_config.config_dir)
    except LocalConfigurationError as local_config_err:
        LOGGER.error(str(local_config_err))
        sys.exit(1)

    # Process initial initialization errors, delaying the sys.exit(1) until
    # all errors have been reported to the user (via LOGGER.error()).  This
    # is intended to provide enough information to the user so they can correct
    # multiple errors before restarting the validator.
    init_errors = False
    try:
        identity_signer = load_identity_signer(key_dir=path_config.key_dir,
                                               key_name='validator')
    except LocalConfigurationError as e:
        log_configuration(log_dir=path_config.log_dir, name="validator")
        LOGGER.error(str(e))
        init_errors = True

    log_config = get_log_config()
    if not init_errors:
        if log_config is not None:
            log_configuration(log_config=log_config)
            if log_config.get('root') is not None:
                init_console_logging(verbose_level=args['verbose'])
        else:
            log_configuration(log_dir=path_config.log_dir, name="validator")

    try:
        version = pkg_resources.get_distribution(DISTRIBUTION_NAME).version
    except pkg_resources.DistributionNotFound:
        version = 'UNKNOWN'
    LOGGER.info('%s (Hyperledger Sawtooth) version %s', DISTRIBUTION_NAME,
                version)

    if LOGGER.isEnabledFor(logging.INFO):
        LOGGER.info('; '.join([
            'config [path]: {}'.format(line)
            for line in path_config.to_toml_string()
        ]))

    if not check_directory(path=path_config.data_dir,
                           human_readable_name='Data'):
        init_errors = True
    if not check_directory(path=path_config.log_dir,
                           human_readable_name='Log'):
        init_errors = True

    endpoint = validator_config.endpoint
    if endpoint is None:
        # Need to use join here to get the string "0.0.0.0". Otherwise,
        # bandit thinks we are binding to all interfaces and returns a
        # Medium security risk.
        interfaces = ["*", ".".join(["0", "0", "0", "0"])]
        interfaces += netifaces.interfaces()
        endpoint = validator_config.bind_network
        parsed_endpoint = urlparse(validator_config.bind_network)
        for interface in interfaces:
            if interface == parsed_endpoint.hostname:
                LOGGER.error("Endpoint must be set when using %s", interface)
                init_errors = True

    if init_errors:
        LOGGER.error("Initialization errors occurred (see previous log "
                     "ERROR messages), shutting down.")
        sys.exit(1)
    bind_network = validator_config.bind_network
    bind_component = validator_config.bind_component

    if "tcp://" not in bind_network:
        bind_network = "tcp://" + bind_network

    if "tcp://" not in bind_component:
        bind_component = "tcp://" + bind_component

    if validator_config.network_public_key is None or \
            validator_config.network_private_key is None:
        LOGGER.warning("Network key pair is not configured, Network "
                       "communications between validators will not be "
                       "authenticated or encrypted.")

    metrics_reporter = None
    if validator_config.opentsdb_url:
        LOGGER.info("Adding metrics reporter: url=%s, db=%s",
                    validator_config.opentsdb_url,
                    validator_config.opentsdb_db)

        url = urlparse(validator_config.opentsdb_url)
        proto, db_server, db_port, = url.scheme, url.hostname, url.port

        registry = MetricsRegistry()
        metrics.init_metrics(registry=registry)

        metrics_reporter = InfluxReporter(
            registry=registry,
            reporting_interval=10,
            database=validator_config.opentsdb_db,
            prefix="sawtooth_validator",
            port=db_port,
            protocol=proto,
            server=db_server,
            username=validator_config.opentsdb_username,
            password=validator_config.opentsdb_password)
        metrics_reporter.start()
    else:
        metrics.init_metrics()

    # Verify state integrity before startup
    global_state_db, blockstore = state_verifier.get_databases(
        bind_network, path_config.data_dir)

    state_verifier.verify_state(global_state_db, blockstore, bind_component,
                                validator_config.scheduler)

    # Explicitly drop this, so there are not two db instances
    global_state_db.drop()
    global_state_db = None

    LOGGER.info('Starting validator with %s scheduler',
                validator_config.scheduler)

    validator = Validator(bind_network,
                          bind_component,
                          endpoint,
                          validator_config.peering,
                          validator_config.seeds,
                          validator_config.peers,
                          path_config.data_dir,
                          path_config.config_dir,
                          identity_signer,
                          validator_config.scheduler,
                          validator_config.permissions,
                          validator_config.minimum_peer_connectivity,
                          validator_config.maximum_peer_connectivity,
                          validator_config.network_public_key,
                          validator_config.network_private_key,
                          roles=validator_config.roles)

    # pylint: disable=broad-except
    try:
        validator.start()
    except KeyboardInterrupt:
        LOGGER.info("Initiating graceful "
                    "shutdown (press Ctrl+C again to force)")
    except LocalConfigurationError as local_config_err:
        LOGGER.error(str(local_config_err))
        sys.exit(1)
    except GenesisError as genesis_err:
        LOGGER.error(str(genesis_err))
        sys.exit(1)
    except Exception as e:
        LOGGER.exception(e)
        sys.exit(1)
    finally:
        if metrics_reporter:
            metrics_reporter.stop()
        validator.stop()
예제 #2
0
def main(args):
    try:
        path_config = load_path_config(config_dir=args['config_dir'])
    except LocalConfigurationError as local_config_err:
        LOGGER.error(str(local_config_err))
        sys.exit(1)

    try:
        opts_config = ValidatorConfig(
            bind_component=args['bind_component'],
            bind_network=args['bind_network'],
            bind_consensus=args['bind_consensus'],
            endpoint=args['endpoint'],
            maximum_peer_connectivity=args['maximum_peer_connectivity'],
            minimum_peer_connectivity=args['minimum_peer_connectivity'],
            roles=args['roles'],
            opentsdb_db=args['opentsdb_db'],
            opentsdb_url=args['opentsdb_url'],
            peering=args['peering'],
            peers=args['peers'],
            scheduler=args['scheduler'],
            seeds=args['seeds'],
            state_pruning_block_depth=args['state_pruning_block_depth'],
            fork_cache_keep_time=args['fork_cache_keep_time'],
        )

        validator_config = \
            load_validator_config(opts_config, path_config.config_dir)
    except LocalConfigurationError as local_config_err:
        LOGGER.error(str(local_config_err))
        sys.exit(1)

    try:
        log_configuration(log_dir=path_config.log_dir,
                          name="validator")
    except LocalConfigurationError as local_config_err:
        LOGGER.error(str(local_config_err))
        sys.exit(1)

    # Process initial initialization errors, delaying the sys.exit(1) until
    # all errors have been reported to the user (via LOGGER.error()).  This
    # is intended to provide enough information to the user so they can correct
    # multiple errors before restarting the validator.
    init_errors = False
    try:
        identity_signer = load_identity_signer(
            key_dir=path_config.key_dir,
            key_name='validator')
    except LocalConfigurationError as e:
        LOGGER.error(str(e))
        init_errors = True

    log_config = get_log_config()
    if not init_errors:
        if log_config is not None:
            log_configuration(log_config=log_config)
            if log_config.get('root') is not None:
                init_console_logging(verbose_level=args['verbose'])
        else:
            log_configuration(log_dir=path_config.log_dir,
                              name="validator")

    try:
        version = pkg_resources.get_distribution(DISTRIBUTION_NAME).version
    except pkg_resources.DistributionNotFound:
        version = 'UNKNOWN'
    LOGGER.info(
        '%s (Hyperledger Sawtooth) version %s', DISTRIBUTION_NAME, version)

    if LOGGER.isEnabledFor(logging.INFO):
        LOGGER.info(
            '; '.join([
                'config [path]: {}'.format(line)
                for line in path_config.to_toml_string()
            ])
        )

    if not check_directory(path=path_config.data_dir,
                           human_readable_name='Data'):
        init_errors = True
    if not check_directory(path=path_config.log_dir,
                           human_readable_name='Log'):
        init_errors = True

    endpoint = validator_config.endpoint
    if endpoint is None:
        # Need to use join here to get the string "0.0.0.0". Otherwise,
        # bandit thinks we are binding to all interfaces and returns a
        # Medium security risk.
        interfaces = ["*", ".".join(["0", "0", "0", "0"])]
        interfaces += netifaces.interfaces()
        endpoint = validator_config.bind_network
        parsed_endpoint = urlparse(validator_config.bind_network)
        for interface in interfaces:
            if interface == parsed_endpoint.hostname:
                LOGGER.error("Endpoint must be set when using %s", interface)
                init_errors = True

    if init_errors:
        LOGGER.error("Initialization errors occurred (see previous log "
                     "ERROR messages), shutting down.")
        sys.exit(1)
    bind_network = validator_config.bind_network
    bind_component = validator_config.bind_component
    bind_consensus = validator_config.bind_consensus

    if "tcp://" not in bind_network:
        bind_network = "tcp://" + bind_network

    if "tcp://" not in bind_component:
        bind_component = "tcp://" + bind_component

    if bind_consensus and "tcp://" not in bind_consensus:
        bind_consensus = "tcp://" + bind_consensus

    if validator_config.network_public_key is None or \
            validator_config.network_private_key is None:
        LOGGER.warning("Network key pair is not configured, Network "
                       "communications between validators will not be "
                       "authenticated or encrypted.")

    metrics_reporter = None
    if validator_config.opentsdb_url:
        LOGGER.info("Adding metrics reporter: url=%s, db=%s",
                    validator_config.opentsdb_url,
                    validator_config.opentsdb_db)

        url = urlparse(validator_config.opentsdb_url)
        proto, db_server, db_port, = url.scheme, url.hostname, url.port

        registry = MetricsRegistry()
        metrics.init_metrics(registry=registry)

        metrics_reporter = InfluxReporter(
            registry=registry,
            reporting_interval=10,
            database=validator_config.opentsdb_db,
            prefix="sawtooth_validator",
            port=db_port,
            protocol=proto,
            server=db_server,
            username=validator_config.opentsdb_username,
            password=validator_config.opentsdb_password)
        metrics_reporter.start()
    else:
        metrics.init_metrics()

    # Verify state integrity before startup
    global_state_db, blockstore = state_verifier.get_databases(
        bind_network,
        path_config.data_dir)

    state_verifier.verify_state(
        global_state_db,
        blockstore,
        bind_component,
        validator_config.scheduler)

    # Explicitly drop this, so there are not two db instances
    global_state_db.drop()
    global_state_db = None

    LOGGER.info(
        'Starting validator with %s scheduler',
        validator_config.scheduler)

    component_workers = validator_config.component_thread_pool_workers
    network_workers = validator_config.network_thread_pool_workers
    sig_workers = validator_config.signature_thread_pool_workers
    validator = Validator(
        bind_network,
        bind_component,
        bind_consensus,
        endpoint,
        validator_config.peering,
        validator_config.seeds,
        validator_config.peers,
        path_config.data_dir,
        path_config.config_dir,
        identity_signer,
        validator_config.scheduler,
        validator_config.permissions,
        validator_config.minimum_peer_connectivity,
        validator_config.maximum_peer_connectivity,
        validator_config.state_pruning_block_depth,
        validator_config.fork_cache_keep_time,
        validator_config.network_public_key,
        validator_config.network_private_key,
        roles=validator_config.roles,
        component_thread_pool_workers=component_workers,
        network_thread_pool_workers=network_workers,
        signature_thread_pool_workers=sig_workers)

    # pylint: disable=broad-except
    try:
        validator.start()
    except KeyboardInterrupt:
        LOGGER.info("Initiating graceful "
                    "shutdown (press Ctrl+C again to force)")
    except LocalConfigurationError as local_config_err:
        LOGGER.error(str(local_config_err))
        sys.exit(1)
    except GenesisError as genesis_err:
        LOGGER.error(str(genesis_err))
        sys.exit(1)
    except Exception as e:
        LOGGER.exception(e)
        sys.exit(1)
    finally:
        if metrics_reporter:
            metrics_reporter.stop()
        validator.stop()