All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.hyperledger.fabric.sdk.helper.Config Maven / Gradle / Ivy

Go to download

Java SDK for Hyperledger Fabric. Deprecated as of Fabric v2.5, replaced by org.hyperledger.fabric:fabric-gateway.

There is a newer version: 2.2.26
Show newest version
/*
 *  Copyright 2016, 2017 IBM, DTCC, Fujitsu Australia Software Technology, IBM - All Rights Reserved.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *  http://www.apache.org/licenses/LICENSE-2.0
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.hyperledger.fabric.sdk.helper;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.Level;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import static java.lang.String.format;

/**
 * Config allows for a global config of the toolkit. Central location for all
 * toolkit configuration defaults. Has a local config file that can override any
 * property defaults. Config file can be relocated via a system property
 * "org.hyperledger.fabric.sdk.configuration". Any property can be overridden
 * with environment variable and then overridden
 * with a java system property. Property hierarchy goes System property
 * overrides environment variable which overrides config file for default values specified here.
 */

public class Config {
    private static final Log logger = LogFactory.getLog(Config.class);

    private static final String DEFAULT_CONFIG = "config.properties";
    public static final String ORG_HYPERLEDGER_FABRIC_SDK_CONFIGURATION = "org.hyperledger.fabric.sdk.configuration";

    private static final String DEFAULT_NULL = "\0DEFAULT_NULL\0".intern(); // Used to set value to NULL since null won't work.
    /**
     * Timeout settings
     **/
    public static final String PROPOSAL_WAIT_TIME = "org.hyperledger.fabric.sdk.proposal.wait.time";
    public static final String CHANNEL_CONFIG_WAIT_TIME = "org.hyperledger.fabric.sdk.channelconfig.wait_time";
    public static final String TRANSACTION_CLEANUP_UP_TIMEOUT_WAIT_TIME = "org.hyperledger.fabric.sdk.client.transaction_cleanup_up_timeout_wait_time";
    public static final String ORDERER_RETRY_WAIT_TIME = "org.hyperledger.fabric.sdk.orderer_retry.wait_time";
    public static final String ORDERER_WAIT_TIME = "org.hyperledger.fabric.sdk.orderer.ordererWaitTimeMilliSecs";
    public static final String PEER_EVENT_REGISTRATION_WAIT_TIME = "org.hyperledger.fabric.sdk.peer.eventRegistration.wait_time";
    public static final String PEER_EVENT_RETRY_WAIT_TIME = "org.hyperledger.fabric.sdk.peer.retry_wait_time";
    public static final String PEER_EVENT_RECONNECTION_WARNING_RATE = "org.hyperledger.fabric.sdk.peer.reconnection_warning_rate";
    public static final String GENESISBLOCK_WAIT_TIME = "org.hyperledger.fabric.sdk.channel.genesisblock_wait_time";
    /**
     * Crypto configuration settings -- settings should not be changed.
     **/
    public static final String DEFAULT_CRYPTO_SUITE_FACTORY = "org.hyperledger.fabric.sdk.crypto.default_crypto_suite_factory";
    public static final String SECURITY_LEVEL = "org.hyperledger.fabric.sdk.security_level";
    public static final String SECURITY_PROVIDER_CLASS_NAME = "org.hyperledger.fabric.sdk.security_provider_class_name";
    public static final String SECURITY_CURVE_MAPPING = "org.hyperledger.fabric.sdk.security_curve_mapping";
    public static final String HASH_ALGORITHM = "org.hyperledger.fabric.sdk.hash_algorithm";
    public static final String ASYMMETRIC_KEY_TYPE = "org.hyperledger.fabric.sdk.crypto.asymmetric_key_type";
    public static final String CERTIFICATE_FORMAT = "org.hyperledger.fabric.sdk.crypto.certificate_format";
    public static final String SIGNATURE_ALGORITHM = "org.hyperledger.fabric.sdk.crypto.default_signature_algorithm";
    /**
     * Logging settings
     **/
    public static final String MAX_LOG_STRING_LENGTH = "org.hyperledger.fabric.sdk.log.stringlengthmax";
    public static final String EXTRALOGLEVEL = "org.hyperledger.fabric.sdk.log.extraloglevel";  // ORG_HYPERLEDGER_FABRIC_SDK_LOG_EXTRALOGLEVEL
    public static final String LOGGERLEVEL = "org.hyperledger.fabric.sdk.loglevel";  // ORG_HYPERLEDGER_FABRIC_SDK_LOGLEVEL=TRACE,DEBUG
    public static final String DIAGNOTISTIC_FILE_DIRECTORY = "org.hyperledger.fabric.sdk.diagnosticFileDir"; //ORG_HYPERLEDGER_FABRIC_SDK_DIAGNOSTICFILEDIR

    /**
     * Connections settings
     */

    public static final String CONN_SSL_PROVIDER = "org.hyperledger.fabric.sdk.connections.ssl.sslProvider";
    public static final String CONN_SSL_NEGTYPE = "org.hyperledger.fabric.sdk.connections.ssl.negotiationType";

    /**
     * Default HFClient thread executor settings.
     */

    public static final String CLIENT_THREAD_EXECUTOR_COREPOOLSIZE = "org.hyperledger.fabric.sdk.client.thread_executor_corepoolsize";
    public static final String CLIENT_THREAD_EXECUTOR_MAXIMUMPOOLSIZE = "org.hyperledger.fabric.sdk.client.thread_executor_maximumpoolsize";
    public static final String CLIENT_THREAD_EXECUTOR_KEEPALIVETIME = "org.hyperledger.fabric.sdk.client.thread_executor_keepalivetime";
    public static final String CLIENT_THREAD_EXECUTOR_KEEPALIVETIMEUNIT = "org.hyperledger.fabric.sdk.client.thread_executor_keepalivetimeunit";

    /**
     * Miscellaneous settings
     **/
    public static final String PROPOSAL_CONSISTENCY_VALIDATION = "org.hyperledger.fabric.sdk.proposal.consistency_validation";

    public static final String SERVICE_DISCOVER_FREQ_SECONDS = "org.hyperledger.fabric.sdk.service_discovery.frequency_sec";
    public static final String SERVICE_DISCOVER_WAIT_TIME = "org.hyperledger.fabric.sdk.service_discovery.discovery_wait_time";
    public static final String SERVICE_DISCOVER_AS_LOCALHOST = "org.hyperledger.fabric.sdk.service_discovery.as_localhost";

    public static final String LIFECYCLE_CHAINCODE_ENDORSEMENT_PLUGIN = "org.hyperledger.fabric.sdk.lifecycle.chaincode_endorsement_plugin"; //ORG_HYPERLEDGER_FABRIC_SDK_LIFECYCLE_CHAINCODE_ENDORSEMENT_PLUGIN

    public static final String LIFECYCLE_CHAINCODE_VALIDATION_PLUGIN = "org.hyperledger.fabric.sdk.lifecycle.chaincode_validation_plugin";   //ORG_HYPERLEDGER_FABRIC_SDK_LIFECYCLE_CHAINCODE_VALIDATION_PLUGIN
    public static final String LIFECYCLE_INITREQUIREDDEFAULT = "org.hyperledger.fabric.sdk.lifecycle.initRequiredDefault";   //ORG_HYPERLEDGER_FABRIC_SDK_LIFECYCLE_INITREQUIREDDEFAULT

    private static Config config;
    private static final Properties sdkProperties = new Properties();
    private static final AtomicLong count = new AtomicLong(0);
    private final OpenTelemetrySdk openTelemetry;

    //Provides a unique id for logging to identify a specific instance.
    public String getNextID() {
        return "" + count.incrementAndGet();
    }

    private Config() {
        File loadFile;
        FileInputStream configProps;

        try {
            loadFile = new File(System.getProperty(ORG_HYPERLEDGER_FABRIC_SDK_CONFIGURATION, DEFAULT_CONFIG))
                    .getAbsoluteFile();
            logger.debug(format("Loading configuration from %s and it is present: %b", loadFile.toString(),
                    loadFile.exists()));
            configProps = new FileInputStream(loadFile);
            sdkProperties.load(configProps);

        } catch (IOException e) {
            logger.warn(format("Failed to load any configuration from: %s. Using toolkit defaults",
                    DEFAULT_CONFIG));
        } finally {

            // Default values
            /**
             * Timeout settings
             **/
            defaultProperty(PROPOSAL_WAIT_TIME, "120000");
            defaultProperty(CHANNEL_CONFIG_WAIT_TIME, "15000");
            defaultProperty(ORDERER_RETRY_WAIT_TIME, "200");
            defaultProperty(ORDERER_WAIT_TIME, "10000");
            defaultProperty(PEER_EVENT_REGISTRATION_WAIT_TIME, "5000");
            defaultProperty(PEER_EVENT_RETRY_WAIT_TIME, "500");
            defaultProperty(GENESISBLOCK_WAIT_TIME, "5000");
            /**
             * This will NOT complete any transaction futures time out and must be kept WELL above any expected future timeout
             * for transactions sent to the Orderer. For internal cleanup only.
             */

            defaultProperty(TRANSACTION_CLEANUP_UP_TIMEOUT_WAIT_TIME, "600000"); //10 min.

            /**
             * Crypto configuration settings
             **/
            defaultProperty(DEFAULT_CRYPTO_SUITE_FACTORY, "org.hyperledger.fabric.sdk.security.HLSDKJCryptoSuiteFactory");
            defaultProperty(SECURITY_LEVEL, "256");
            defaultProperty(SECURITY_PROVIDER_CLASS_NAME, BouncyCastleProvider.class.getName());
            defaultProperty(SECURITY_CURVE_MAPPING, "256=secp256r1:384=secp384r1");
            defaultProperty(HASH_ALGORITHM, "SHA2");
            defaultProperty(ASYMMETRIC_KEY_TYPE, "EC");

            defaultProperty(CERTIFICATE_FORMAT, "X.509");
            defaultProperty(SIGNATURE_ALGORITHM, "SHA256withECDSA");

            /**
             * Connection defaults
             */

            defaultProperty(CONN_SSL_PROVIDER, "openSSL");
            defaultProperty(CONN_SSL_NEGTYPE, "TLS");

            /**
             * Default HFClient thread executor settings.
             */

            int availableProcessors = Runtime.getRuntime().availableProcessors();
            defaultProperty(CLIENT_THREAD_EXECUTOR_COREPOOLSIZE, Integer.toString(availableProcessors + 1));
            defaultProperty(CLIENT_THREAD_EXECUTOR_MAXIMUMPOOLSIZE, Integer.toString(availableProcessors + 1));
            defaultProperty(CLIENT_THREAD_EXECUTOR_KEEPALIVETIME, "60");
            defaultProperty(CLIENT_THREAD_EXECUTOR_KEEPALIVETIMEUNIT, "SECONDS");

            /**
             * Logging settings
             **/
            defaultProperty(MAX_LOG_STRING_LENGTH, "64");
            defaultProperty(EXTRALOGLEVEL, "0");
            defaultProperty(LOGGERLEVEL, null);
            defaultProperty(DIAGNOTISTIC_FILE_DIRECTORY, null);
            /**
             * Miscellaneous settings
             */
            defaultProperty(PROPOSAL_CONSISTENCY_VALIDATION, "true");
            defaultProperty(PEER_EVENT_RECONNECTION_WARNING_RATE, "50");

            defaultProperty(SERVICE_DISCOVER_FREQ_SECONDS, "120");
            defaultProperty(SERVICE_DISCOVER_WAIT_TIME, "5000");
            defaultProperty(SERVICE_DISCOVER_AS_LOCALHOST, "false");
            defaultProperty(LIFECYCLE_CHAINCODE_ENDORSEMENT_PLUGIN, DEFAULT_NULL);
            defaultProperty(LIFECYCLE_CHAINCODE_VALIDATION_PLUGIN, DEFAULT_NULL);
            defaultProperty(LIFECYCLE_INITREQUIREDDEFAULT, DEFAULT_NULL);

            final String inLogLevel = sdkProperties.getProperty(LOGGERLEVEL);

            if (null != inLogLevel) {

                org.apache.log4j.Level setTo;

                switch (inLogLevel.toUpperCase()) {

                    case "TRACE":
                        setTo = org.apache.log4j.Level.TRACE;
                        break;

                    case "DEBUG":
                        setTo = org.apache.log4j.Level.DEBUG;
                        break;

                    case "INFO":
                        setTo = Level.INFO;
                        break;

                    case "WARN":
                        setTo = Level.WARN;
                        break;

                    case "ERROR":
                        setTo = Level.ERROR;
                        break;

                    default:
                        setTo = Level.INFO;
                        break;

                }

                if (null != setTo) {
                    org.apache.log4j.Logger.getLogger("org.hyperledger.fabric").setLevel(setTo);
                }

            }

            openTelemetry = AutoConfiguredOpenTelemetrySdk
                .builder()
                .setResultAsGlobal(false)
                .build()
                .getOpenTelemetrySdk();
        }

    }

    /**
     * getConfig return back singleton for SDK configuration.
     *
     * @return Global configuration
     */
    public static Config getConfig() {
        if (null == config) {
            config = new Config();
        }
        return config;

    }

    /**
     * getProperty return back property for the given value.
     *
     * @param property
     * @return String value for the property
     */
    private String getProperty(String property) {

        if (!sdkProperties.containsKey(property)) {
            logger.warn(format("No configuration value found for '%s'", property));
        }
        String ret = sdkProperties.getProperty(property);
        if (DEFAULT_NULL.equals(ret)) {
            ret = null;
        }
        return ret;
    }

    private static void defaultProperty(String key, String value) {

        String ret = System.getProperty(key);
        if (ret != null) {
            sdkProperties.put(key, ret);
        } else {
            String envKey = key.toUpperCase().replaceAll("\\.", "_");
            ret = System.getenv(envKey);
            if (null != ret) {
                sdkProperties.put(key, ret);
            } else {
                if (null == sdkProperties.getProperty(key) && value != null) {
                    sdkProperties.put(key, value);
                }

            }

        }
    }

    /**
     * Get the configured security level. The value determines the elliptic curve used to generate keys.
     *
     * @return the security level.
     */
    public int getSecurityLevel() {

        return Integer.parseInt(getProperty(SECURITY_LEVEL));

    }

    /**
     * Get the configured security provider.
     * This is the security provider used for the default SDK crypto suite factory.
     *
     * @return the security provider.
     */
    public String getSecurityProviderClassName() {
        return getProperty(SECURITY_PROVIDER_CLASS_NAME);
    }

    /**
     * Get the name of the configured hash algorithm, used for digital signatures.
     *
     * @return the hash algorithm name.
     */
    public String getHashAlgorithm() {
        return getProperty(HASH_ALGORITHM);

    }

    /**
     * The default ssl provider for grpc connection
     *
     * @return The default ssl provider for grpc connection
     */
    public String getDefaultSSLProvider() {
        return getProperty(CONN_SSL_PROVIDER);

    }

    /**
     * The default ssl negotiation type
     *
     * @return The default ssl negotiation type
     */

    public String getDefaultSSLNegotiationType() {
        return getProperty(CONN_SSL_NEGTYPE);

    }

    public OpenTelemetry getOpenTelemetry() {
        return openTelemetry;
    }

    private Map curveMapping = null;

    /**
     * Get a mapping from strength to curve desired.
     *
     * @return mapping from strength to curve name to use.
     */
    public Map getSecurityCurveMapping() {

        if (curveMapping == null) {

            curveMapping = parseSecurityCurveMappings(getProperty(SECURITY_CURVE_MAPPING));
        }

        return Collections.unmodifiableMap(curveMapping);
    }

    public static Map parseSecurityCurveMappings(final String property) {
        Map lcurveMapping = new HashMap<>(8);

        if (property != null && !property.isEmpty()) { //empty will be caught later.

            String[] cmaps = property.split("[ \t]*:[ \t]*");
            for (String mape : cmaps) {

                String[] ep = mape.split("[ \t]*=[ \t]*");
                if (ep.length != 2) {
                    logger.warn(format("Bad curve mapping for %s in property %s", mape, SECURITY_CURVE_MAPPING));
                    continue;
                }

                try {
                    int parseInt = Integer.parseInt(ep[0]);
                    lcurveMapping.put(parseInt, ep[1]);
                } catch (NumberFormatException e) {
                    logger.warn(format("Bad curve mapping. Integer needed for strength %s for %s in property %s",
                            ep[0], mape, SECURITY_CURVE_MAPPING));
                }

            }

        }
        return lcurveMapping;
    }

    /**
     * Get the timeout for a single proposal request to endorser.
     *
     * @return the timeout in milliseconds.
     */
    public long getProposalWaitTime() {
        return Long.parseLong(getProperty(PROPOSAL_WAIT_TIME));
    }

    /**
     * Get the configured time to wait for genesis block.
     *
     * @return time in milliseconds.
     */
    public long getGenesisBlockWaitTime() {
        return Long.parseLong(getProperty(GENESISBLOCK_WAIT_TIME));
    }

    /**
     * Time to wait for channel to be configured.
     *
     * @return
     */
    public long getChannelConfigWaitTime() {
        return Long.parseLong(getProperty(CHANNEL_CONFIG_WAIT_TIME));
    }

    /**
     * Time to wait before retrying an operation.
     *
     * @return
     */
    public long getOrdererRetryWaitTime() {
        return Long.parseLong(getProperty(ORDERER_RETRY_WAIT_TIME));
    }

    public long getOrdererWaitTime() {
        return Long.parseLong(getProperty(ORDERER_WAIT_TIME));
    }

    /**
     * getPeerEventRegistrationWaitTime
     *
     * @return time in milliseconds to wait for peer eventing service to wait for event registration
     */
    public long getPeerEventRegistrationWaitTime() {
        return Long.parseLong(getProperty(PEER_EVENT_REGISTRATION_WAIT_TIME));
    }

    /**
     * getPeerEventRegistrationWaitTime
     *
     * @return time in milliseconds to wait for peer eventing service to wait for event registration
     */
    public long getPeerRetryWaitTime() {
        return Long.parseLong(getProperty(PEER_EVENT_RETRY_WAIT_TIME));
    }

    public long getPeerEventReconnectionWarningRate() {
        return Long.parseLong(getProperty(PEER_EVENT_RECONNECTION_WARNING_RATE));
    }

    /**
     * How often serviced discovery is preformed in seconds.
     *
     * @return
     */
    public int getServiceDiscoveryFreqSeconds() {
        return Integer.parseInt(getProperty(SERVICE_DISCOVER_FREQ_SECONDS));
    }

    /**
     * Time to wait for service discovery to complete.
     *
     * @return
     */
    public int getServiceDiscoveryWaitTime() {
        return Integer.parseInt(getProperty(SERVICE_DISCOVER_WAIT_TIME));
    }

    public boolean discoverAsLocalhost() {
        return Boolean.parseBoolean(getProperty(SERVICE_DISCOVER_AS_LOCALHOST));
    }

    public String getAsymmetricKeyType() {
        return getProperty(ASYMMETRIC_KEY_TYPE);
    }

    public String getCertificateFormat() {
        return getProperty(CERTIFICATE_FORMAT);
    }

    public String getSignatureAlgorithm() {
        return getProperty(SIGNATURE_ALGORITHM);
    }

    public String getDefaultCryptoSuiteFactory() {
        return getProperty(DEFAULT_CRYPTO_SUITE_FACTORY);
    }

    public int maxLogStringLength() {
        return Integer.parseInt(getProperty(MAX_LOG_STRING_LENGTH));
    }

    /**
     * getProposalConsistencyValidation determine if validation of the proposals should
     * be done before sending to the orderer.
     *
     * @return if true proposals will be checked they are consistent with each other before sending to the Orderer
     */

    public boolean getProposalConsistencyValidation() {
        return Boolean.parseBoolean(getProperty(PROPOSAL_CONSISTENCY_VALIDATION));

    }

    private int extraLogLevel = -1;

    public boolean extraLogLevel(int val) {
        if (extraLogLevel == -1) {
            extraLogLevel = Integer.parseInt(getProperty(EXTRALOGLEVEL));
        }

        return val <= extraLogLevel;

    }

    DiagnosticFileDumper diagnosticFileDumper = null;

    /**
     * The directory where diagnostic dumps are to be place, null if none should be done.
     *
     * @return The directory where diagnostic dumps are to be place, null if none should be done.
     */

    public DiagnosticFileDumper getDiagnosticFileDumper() {

        if (diagnosticFileDumper != null) {
            return diagnosticFileDumper;
        }

        String dd = sdkProperties.getProperty(DIAGNOTISTIC_FILE_DIRECTORY);

        if (dd != null) {

            diagnosticFileDumper = DiagnosticFileDumper.configInstance(new File(dd));

        }

        return diagnosticFileDumper;
    }

    /**
     * This does NOT trigger futures time out and must be kept WELL above any expected future timeout
     * for transactions sent to the Orderer
     *
     * @return
     */
    public long getTransactionListenerCleanUpTimeout() {
        return Long.parseLong(getProperty(TRANSACTION_CLEANUP_UP_TIMEOUT_WAIT_TIME));
    }

    /**
     * The number of threads to keep in the pool, even if they are idle, unless {@code allowCoreThreadTimeOut} is set
     *
     * @return The number of threads to keep in the pool, even if they are idle, unless {@code allowCoreThreadTimeOut} is set
     */

    public int getClientThreadExecutorCorePoolSize() {
        return Integer.parseInt(getProperty(CLIENT_THREAD_EXECUTOR_COREPOOLSIZE));
    }

    /**
     * maximumPoolSize the maximum number of threads to allow in the pool
     *
     * @return maximumPoolSize the maximum number of threads to allow in the pool
     */
    public int getClientThreadExecutorMaxiumPoolSize() {
        return Integer.parseInt(getProperty(CLIENT_THREAD_EXECUTOR_MAXIMUMPOOLSIZE));
    }

    /**
     * keepAliveTime when the number of threads is greater than
     * the core, this is the maximum time that excess idle threads
     * will wait for new tasks before terminating.
     *
     * @return The keep alive time.
     */

    public long getClientThreadExecutorKeepAliveTime() {
        return Long.parseLong(getProperty(CLIENT_THREAD_EXECUTOR_KEEPALIVETIME));
    }

    /**
     * the time unit for the argument
     *
     * @return
     */

    public TimeUnit getClientThreadExecutorKeepAliveTimeUnit() {

        return TimeUnit.valueOf(getProperty(CLIENT_THREAD_EXECUTOR_KEEPALIVETIMEUNIT));
    }

    /**
     * The default chaincode Endorsement policy plugin
     * 

* This should never need setting * * @return The default chaincode Endorsement policy plugin */ public String getDefaultChaincodeEndorsementPlugin() { return getProperty(LIFECYCLE_CHAINCODE_ENDORSEMENT_PLUGIN); } /** * The default chaincode validation plugin * This should never need setting. * * @return The default chaincode validation plugin */ public String getDefaultChaincodeValidationPlugin() { return getProperty(LIFECYCLE_CHAINCODE_VALIDATION_PLUGIN); } /** * Whether require init method in chaincode to be run. * The default will return null which will not set the Fabric protobuf value which then sets false. False is the Fabric * default. * * @return The default setting for initRequired in chaincode approve for my org and commit chaincode definition. */ public Boolean getLifecycleInitRequiredDefault() { String property = getProperty(LIFECYCLE_INITREQUIREDDEFAULT); if (property != null) { return Boolean.parseBoolean(property); } return null; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy