コード例 #1
0
        static (T, Key, string) LoadKeyStore <T>(Base.Storage storage, string service, string keyName, string path = null) where T : KeyStore
        {
            try
            {
                var p = "keys/";
                if (path != null)
                {
                    p = $"keys/{path}/";
                }

                var name = GetKeyStoreName(service, keyName);

                var keyStoreData = storage.ReadFileText($"{p}{name} Keystore.txt");
                if (keyStoreData != null)
                {
                    var keyStorage = KeyStore.Restore <T>(keyStoreData);

                    var password = storage.ReadFileText($"{p}{name} Keystore Password.txt");

                    keyStorage.DecryptKeyAsync(password, true).Wait();

                    return(keyStorage, keyStorage.DecryptedKey, password);
                }
            }
            catch (Exception ex)
            {
                Log.HandleException(ex);
            }

            return(null, null, null);
        }
コード例 #2
0
        public static SortedList <long, TransactionSliceInfo> GetTransactionSlices(Base.Storage storage, ChainType chainType, int chainId, uint chainIndex, bool finalizedOnly)
        {
            var chainPath  = GetTransactionStoragePath(chainType, chainId, chainIndex);
            var discSlices = storage.GetFiles(chainPath, "*.header");

            var result = new SortedList <long, TransactionSliceInfo>();

            foreach (var slice in discSlices)
            {
                var sliceId  = int.Parse(slice.Name.Split('.')[0]);
                var info     = DiscStorage.GetHeader(storage, Path.Combine(chainPath, sliceId.ToString()));
                var userData = new Unpacker(info.UserData);

                var firstBlockId = Protocol.InvalidBlockId;
                var blockId      = Protocol.InvalidBlockId;
                var split        = false;

                if (userData.UnpackBool())
                {
                    firstBlockId = userData.UnpackLong();
                    blockId      = userData.UnpackLong();
                    split        = userData.UnpackBool();
                }

                if (!finalizedOnly || split)
                {
                    result.Add(sliceId, new TransactionSliceInfo(sliceId, firstBlockId, blockId, split, info.Count, info.StartIndex, info.EndIndex));
                }
            }

            return(result);
        }
コード例 #3
0
        static (CoreAccountKeyStore, Key, string) LoadCoreAccountKey(Base.Storage storage, string name, string path = null)
        {
            try
            {
                var p = "keys/";
                if (path != null)
                {
                    p = $"keys/{path}/";
                }

                //name = name.ToLower().Replace(" ", "");

                var keyStoreData = storage.ReadFileText($"{p}{name} Keystore.txt");
                if (keyStoreData != null)
                {
                    var keyStorage = KeyStore.Restore <CoreAccountKeyStore>(keyStoreData);

                    var password = storage.ReadFileText($"{p}{name} Keystore Password.txt");
                    keyStorage.DecryptKeyAsync(password, true).Wait();

                    return(keyStorage, keyStorage.DecryptedKey, password);
                }
            }
            catch { }

            return(null, null, null);
        }
コード例 #4
0
        public static SortedList <long, BlockSliceInfo> GetBlockSlices(Base.Storage storage, ChainType chainType, int chainId, uint chainIndex, bool finalizedOnly)
        {
            var result        = new SortedList <long, BlockSliceInfo>();
            var path          = GetBlockStoragePath(chainType, chainId, chainIndex);
            var blockStorages = storage.GetFiles(path, "*.header");

            foreach (var blockStorage in blockStorages)
            {
                var sliceIndex = long.Parse(blockStorage.Name.Split('.')[0]);
                var blockInfo  = new BlockSliceInfo(sliceIndex);

                var header = DiscStorage.GetHeader(storage, Path.Combine(path, sliceIndex.ToString()));
                if (header.Count > 0)
                {
                    blockInfo.FirstBlockId = header.StartIndex;
                    blockInfo.LastBlockId  = header.EndIndex;
                }

                if (finalizedOnly)
                {
                    if (blockInfo.Finalized)
                    {
                        result.Add(sliceIndex, blockInfo);
                    }
                }
                else
                {
                    result.Add(sliceIndex, blockInfo);
                }
            }

            return(result);
        }
コード例 #5
0
        public BlockDiscStorage(Base.Storage storage, ChainType chainType, int chainId, uint chainIndex, long sliceIndex, bool readOnly) : base(storage, Path.Combine(BlockStorage.GetBlockStoragePath(chainType, chainId, chainIndex), sliceIndex.ToString()), 256, 32, DiscStorageFlags.AppendOnly | DiscStorageFlags.DynamicBlockSize | (readOnly ? DiscStorageFlags.Readonly : DiscStorageFlags.None))
        {
            SliceIndex = sliceIndex;

            if (UserDataUnpacker.UnpackBool())
            {
                UserDataUnpacker.UnpackUshort();
            }
        }
コード例 #6
0
 public MetaDiscStorage(Base.Storage storage, ChainType chainType, int chainId, uint chainIndex, string name, int blockSize, DiscStorageFlags flags, int userDataSize = 20) : base(storage, Path.Combine(Chain.GetChainMetaDirectory(chainType, chainId, chainIndex), name), blockSize, userDataSize, flags)
 {
     if (UserDataUnpacker.UnpackBool())
     {
         LastBlockId       = UserDataUnpacker.UnpackLong();
         LastTransactionId = UserDataUnpacker.UnpackLong();
         MetaUnpack();
     }
 }
コード例 #7
0
        public static void CreateRequiredDirectories(Base.Storage storage, ChainType chainType, int chainId, uint chainIndex)
        {
            var path = GetTransactionStoragePath(chainType, chainId, chainIndex);

            if (!storage.CreateDirectory(path))
            {
                throw new Exception($"Could not create directory {path}.");
            }
        }
コード例 #8
0
 public TransactionDiscStorage(Base.Storage storage, string name, int blockSize, DiscStorageFlags flags) : base(storage, name, blockSize, 32, flags)
 {
     if (UserDataUnpacker.UnpackBool())
     {
         UserDataUnpacker.UnpackUshort();
         FirstBlockId = UserDataUnpacker.UnpackLong();
         LastBlockId  = UserDataUnpacker.UnpackLong();
         Split        = UserDataUnpacker.UnpackBool();
     }
 }
コード例 #9
0
            public ChainAttachementsCache(Base.Storage storage, DataChain chain)
            {
                Chain = chain;

                AttachementsPath     = GetAttachementPath(chain.ChainId, chain.ChainIndex, chain.AttachementKey);
                AttachementsFullPath = Path.Combine(storage.Root.FullName, AttachementsPath);

                if (!storage.CreateDirectory(AttachementsPath))
                {
                    throw new Exception("Could not create attachements directory.");
                }
            }
コード例 #10
0
        static void SaveCoreAccountKey(Base.Storage storage, CoreAccountKeyStore keyStore, string name, string password, string path = null)
        {
            var p = "keys/";

            if (path != null)
            {
                p = $"keys/{path}/";
            }

            storage.CreateDirectory(p);

            storage.WriteFileText($"{p}/{name} Keystore.txt", $"{name}|{keyStore.HexString}");
            storage.WriteFileText($"{p}/{name} Keystore Password.txt", password);
        }
コード例 #11
0
        static void SaveKeyStore(Base.Storage storage, KeyStore keyStore, string password, string service, string keyName, string path = null)
        {
            var p = "keys/";

            if (path != null)
            {
                p = $"keys/{path}/";
            }

            var name = GetKeyStoreName(service, keyName);

            storage.CreateDirectory(p);

            storage.WriteFileText($"{p}{name} Keystore.txt", $"{keyName}|{keyStore.HexString}");
            storage.WriteFileText($"{p}{name} Keystore Password.txt", password);
        }
コード例 #12
0
        public BlockStorage(ChainType chainType, int chainId, uint chainIndex, Node.Node node)
        {
            ChainType  = chainType;
            ChainId    = chainId;
            ChainIndex = chainIndex;

            _storage = node.Storage;

            _blocksPath          = GetBlockStoragePath(chainType, chainId, chainIndex);
            FullBlockStoragePath = Path.Combine(_storage.Root.FullName, _blocksPath);

            CreateRequiredDirectories(_storage, chainType, chainId, chainIndex);

            CheckBlockSlices();

            _blockLoader = new ConcurrentLoader <long, BlockData>(QueryBlock, LoadBlock);

            History = new BlockTransactionHistory(this, 25);
        }
コード例 #13
0
ファイル: ServiceHost.cs プロジェクト: HeleusCore/Heleus.Node
        public static Type GetServiceType(Base.Storage storage, int chainId, string serviceName, string serviceSearchPath)
        {
            Type serviceType = null;

            if (!serviceName.IsNullOrEmpty())
            {
                var directories = new List <DirectoryInfo>
                {
                    new DirectoryInfo(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)),
                    new DirectoryInfo(Path.Combine(storage.Root.FullName, "services"))
                };

                if (!serviceSearchPath.IsNullOrEmpty())
                {
                    directories.Add(new DirectoryInfo(serviceSearchPath));
                }

                var services = FindServiceAssemblies(serviceName, directories);
                if (services.Count == 1)
                {
                    serviceType = services[0];
                }
                else if (services.Count == 0)
                {
                    Log.Warn($"Could not find service {serviceName} for chainid {chainId}.");
                }
                else
                {
                    var text = string.Empty;
                    foreach (var item in services)
                    {
                        text += $"{item.FullName} in {item.Assembly.Location} ";
                    }

                    Log.Warn($"Multiple valid services {serviceName} found for chainid {chainId}, {text}.");
                }
            }

            return(serviceType);
        }
コード例 #14
0
        public TransactionStorage(Base.Storage storage, ChainType chainType, int chainId, uint chainIndex)
        {
            _blockSize    = 0;
            _storageFlags = DiscStorageFlags.DynamicBlockSize;
            _storage      = storage;

            ChainId    = chainId;
            ChainIndex = chainIndex;

            TransactionsPath            = GetTransactionStoragePath(chainType, chainId, chainIndex);
            FullTransactionsStoragePath = Path.Combine(storage.Root.FullName, TransactionsPath);

            CreateRequiredDirectories(storage, chainType, chainId, chainIndex);

            _currentSliceId = 0;
            _slices         = GetTransactionSlices(storage, chainType, chainId, chainIndex, false);

            // remove the last "hot" slice
            if (_slices.Count > 0)
            {
                var last = _slices.Last().Value;
                if (last.Finalized)
                {
                    _currentSliceId = last.SliceId + 1;
                }
                else
                {
                    _currentSliceId = last.SliceId;
                    _slices.RemoveAt(_slices.Count - 1);
                }
            }

            _transactionSlice = new TransactionDiscStorage(_storage, Path.Combine(TransactionsPath, _currentSliceId.ToString()), _blockSize, _storageFlags);

            _currentFirsBlockId = _transactionSlice.FirstBlockId;
            _currentBlockId     = _transactionSlice.LastBlockId;
        }
コード例 #15
0
        public static GenesisBlockResult Generate(Base.Storage storage)
        {
            (var networkKeyStore, var networkKey, _) = LoadCoreAccountKey(storage, "Network Account", "Heleus Core");

            if (networkKeyStore == null)
            {
                networkKey = Key.Generate(KeyTypes.Ed25519);
                var networkPassword = Hex.ToString(Rand.NextSeed(32));
                networkKeyStore = new CoreAccountKeyStore("Heleus Core Network Account", CoreAccount.NetworkAccountId, networkKey, networkPassword);

                SaveCoreAccountKey(storage, networkKeyStore, "Network Account", networkPassword, "Heleus Core");
            }

            Console.WriteLine($"Heleus Core Network Account Key: {networkKey.PublicKey.HexString}.");

            var networkKeys      = new List <NetworkKey>();
            var networkChainKeys = new List <PublicChainKey>();

            for (var i = 0; i < 3; i++)
            {
                var keyFlags = GetCoreKeyFlags(i);
                var keyName  = $"Network {GetKeyName(keyFlags, true)}";

                (var store, var key, var storePassword) = LoadKeyStore <ChainKeyStore>(storage, null, keyName, "Heleus Core");

                if (store == null)
                {
                    key           = Key.Generate(KeyTypes.Ed25519);
                    storePassword = Hex.ToString(Rand.NextSeed(32));

                    var publicChainKey = new PublicChainKey(keyFlags, CoreChain.CoreChainId, 0, 0, (short)i, key);
                    store = new ChainKeyStore($"Heleus Core {keyName}", publicChainKey, key, storePassword);

                    SaveKeyStore(storage, store, storePassword, null, keyName, "Heleus Core");
                }

                Console.WriteLine($"Heleus Core {keyName}: {key.PublicKey.HexString}.");

                networkKeys.Add(new NetworkKey {
                    Key = key, Password = storePassword, PublicKey = store.PublicChainKey, Store = store
                });
                networkChainKeys.Add(store.PublicChainKey);
            }

            var timestamp = Time.Timestamp;

            timestamp = Protocol.GenesisTime;

            var coreOperations = new List <CoreOperation>();

            var endPoints = new List <string>();

            Console.WriteLine("Type the core chain name (default: Heleus Core)");
            var name = Program.IsDebugging ? "Heleus Core" : Console.ReadLine();

            if (string.IsNullOrWhiteSpace(name))
            {
                name = "Heleus Core";
            }
            Console.WriteLine($"Chain name: {name}");

            Console.WriteLine("Type the core chain website (default: https://heleuscore.com)");
            var website = Program.IsDebugging ? "https://heleuscore.com" : Console.ReadLine();

            if (string.IsNullOrWhiteSpace(website))
            {
                website = "https://heleuscore.com";
            }
            Console.WriteLine($"Chain Website: {website}");

            Console.WriteLine("Type the core chain endpoints. (none for none, default: https://heleusnode.heleuscore.com)");
            while (true)
            {
                if (Program.IsDebugging)
                {
                    var ips = GetLocalIPV4Addresss();
                    foreach (var ip in ips)
                    {
                        endPoints.Add($"http://{ip}:54321/");
                    }
                    break;
                }

                var ep = Console.ReadLine();
                if (string.IsNullOrWhiteSpace(ep))
                {
                    if (endPoints.Count == 0)
                    {
                        endPoints.Add("https://heleusnode.heleuscore.com");
                    }
                    break;
                }

                if (ep.IsValdiUrl(false))
                {
                    Console.WriteLine($"Added endpoint {ep}");
                    endPoints.Add(ep);
                }

                if (ep == "none")
                {
                    break;
                }
            }

            Console.WriteLine($"Chain Endpoints: {string.Join(", ", endPoints)}");

            var useGenesisInfo       = false;
            var useCoreChainEndpoint = false;

            if (storage.FileExists("genesisservices.txt"))
            {
                Console.WriteLine("Process genesisservices.txt [yes/no] (default: yes)");

                var p = Program.IsDebugging ? "yes" : Console.ReadLine();
                if (string.IsNullOrWhiteSpace(p) || p.ToLower() == "yes")
                {
                    Console.WriteLine("Processing genesisservices.txt");

                    useGenesisInfo = true;

                    if (endPoints.Count > 0)
                    {
                        Console.WriteLine("Use first core chain endpoint, not endpoint from genesisservices.txt [yes/no] (default: no)");

                        var p2 = Program.IsDebugging ? "yes" : Console.ReadLine()?.ToLower();

                        if (p2 == "yes")
                        {
                            useCoreChainEndpoint = true;
                            Console.WriteLine($"Using endpoint {endPoints[0]} for all services from genesisservices.txt");
                        }
                    }
                }
            }

            coreOperations.Add((ChainInfoOperation) new ChainInfoOperation(CoreChain.CoreChainId, CoreAccount.NetworkAccountId, name, website, timestamp, networkChainKeys, endPoints, new List <PurchaseInfo>()).UpdateOperationId(Operation.FirstTransactionId));
            coreOperations.Add((AccountOperation) new AccountOperation(CoreAccount.NetworkAccountId, networkKey.PublicKey, timestamp).UpdateOperationId(coreOperations.Count + 1)); // network account
            coreOperations.Add(((AccountUpdateOperation) new AccountUpdateOperation().UpdateOperationId(Operation.FirstTransactionId + 2)).AddAccount(CoreAccount.NetworkAccountId, coreOperations.Count + 1, long.MaxValue / 2).AddTransfer(CoreAccount.NetworkAccountId, CoreAccount.NetworkAccountId, long.MaxValue / 2, null, timestamp));

            var blockStateOperation = new BlockStateOperation();

            var nextChainId       = CoreChain.CoreChainId + 1;
            var nextTransactionId = coreOperations.Count + 1;
            var nextAccountId     = CoreAccount.NetworkAccountId + 1;

            var accounts = new List <AccountOperation>();
            var serviceTransactionsList = new Dictionary <int, List <ServiceTransaction> >();

            if (useGenesisInfo)
            {
                try
                {
                    var json = storage.ReadFileText("genesisservices.txt");
                    if (json != null)
                    {
                        var services = Newtonsoft.Json.JsonConvert.DeserializeObject <List <GenesisService> >(json);
                        if (services != null)
                        {
                            foreach (var service in services)
                            {
                                if (!service.Valid)
                                {
                                    continue;
                                }

                                var serviceKeys = new List <PublicChainKey>();
                                var ep          = useCoreChainEndpoint ? endPoints[0] : service.Endpoint;
                                var accountId   = service.AccountId;

                                if (accountId != CoreAccount.NetworkAccountId)
                                {
                                    var found = accounts.Find((a) => a.AccountId == accountId) != null;
                                    if (!found)
                                    {
                                        (var store, var key, var accountPassword) = LoadCoreAccountKey(storage, "Core Account " + accountId, "Core Accounts");
                                        if (store == null)
                                        {
                                            key             = Key.Generate(KeyTypes.Ed25519);
                                            accountPassword = Hex.ToString(Rand.NextSeed(32));
                                            store           = new CoreAccountKeyStore(service.AccountName, accountId, key, accountPassword);

                                            SaveCoreAccountKey(storage, store, "Core Account " + accountId, accountPassword, "Core Accounts");
                                        }

                                        if (accountId == nextAccountId)
                                        {
                                            var ao = new AccountOperation(accountId, key.PublicKey, timestamp);
                                            ao.UpdateOperationId(nextTransactionId);

                                            coreOperations.Add(ao);
                                            accounts.Add(ao);

                                            nextTransactionId++;
                                            nextAccountId++;
                                        }
                                        else
                                        {
                                            Console.WriteLine($"Invalid account id for {service.Title}, should be {nextAccountId}, but is {accountId}.");
                                            continue;
                                        }
                                    }
                                }

                                Console.WriteLine($"Adding Service {service.Title} with endpoint {ep}.");

                                var count = 2 + service.DataChainCount;
                                for (var i = 0; i < count; i++)
                                {
                                    var keyFlags  = GetServiceKeyFlags(i);
                                    var keyName   = $"{service.Name} {GetKeyName(keyFlags, false)}";
                                    var dataChain = i >= 2;
                                    if (dataChain)
                                    {
                                        keyName += $" (ChainIndex {i - 2})";
                                    }

                                    (var store, var key, var servicePassword) = LoadKeyStore <ChainKeyStore>(storage, null, keyName, service.Name);

                                    if (store == null)
                                    {
                                        key             = Key.Generate(KeyTypes.Ed25519);
                                        servicePassword = Hex.ToString(Rand.NextSeed(32));

                                        var signedKey = new PublicChainKey(keyFlags, nextChainId, dataChain ? (uint)i - 2 : 0, 0, (short)i, key);
                                        store = new ChainKeyStore($"{service.Name} {keyName}", signedKey, key, servicePassword);

                                        SaveKeyStore(storage, store, servicePassword, null, keyName, service.Name);
                                    }

                                    Console.WriteLine($"{service.Name} {keyName}: {key.PublicKey.HexString}.");

                                    serviceKeys.Add(store.PublicChainKey);
                                }

                                var pc = new ChainInfoOperation(nextChainId, accountId, service.Title, service.Website, timestamp, serviceKeys, new List <string> {
                                    ep
                                }, new List <PurchaseInfo>());
                                pc.UpdateOperationId(nextTransactionId);
                                coreOperations.Add(pc);

                                nextTransactionId++;

                                if (service.Revenue > 0)
                                {
                                    var rev = new ChainRevenueInfoOperation(nextChainId, service.Revenue, service.RevenueAccountFactor, timestamp);
                                    rev.UpdateOperationId(nextTransactionId);
                                    coreOperations.Add(rev);
                                    nextTransactionId++;
                                }

                                if (service.Accounts > 0)
                                {
                                    var serviceTransactions = new List <ServiceTransaction>();
                                    for (var i = 0; i < service.Accounts; i++)
                                    {
                                        (var accountStore, var accountKey, var accountPassword) = LoadCoreAccountKey(storage, "Core Account " + nextAccountId, "Core Accounts");
                                        if (accountStore == null)
                                        {
                                            accountKey      = Key.Generate(KeyTypes.Ed25519);
                                            accountPassword = Hex.ToString(Rand.NextSeed(32));
                                            accountStore    = new CoreAccountKeyStore($"Core Account {nextAccountId}", nextAccountId, accountKey, accountPassword);

                                            SaveCoreAccountKey(storage, accountStore, "Core Account " + nextAccountId, accountPassword, "Core Accounts");
                                        }

                                        (var serviceAccountStore, var serviceAccountKey, var serviceAccountPassword) = LoadKeyStore <ServiceAccountKeyStore>(storage, null, $"{service.Name} Service Account {nextAccountId}", $"{service.Name}/Service Accounts");
                                        if (serviceAccountStore == null)
                                        {
                                            serviceAccountKey      = Key.Generate(KeyTypes.Ed25519);
                                            serviceAccountPassword = Hex.ToString(Rand.NextSeed(32));

                                            var signedPublicKey = PublicServiceAccountKey.GenerateSignedPublicKey(nextAccountId, nextChainId, 0, 0, serviceAccountKey.PublicKey, accountKey);
                                            serviceAccountStore = new ServiceAccountKeyStore($"{service.Name} Service Account {nextAccountId}", signedPublicKey, serviceAccountKey, serviceAccountPassword);

                                            SaveKeyStore(storage, serviceAccountStore, serviceAccountPassword, null, $"{service.Name} Service Account {nextAccountId}", $"{service.Name}/Service Accounts");
                                        }

                                        var join = new JoinServiceTransaction(serviceAccountStore.SignedPublicKey)
                                        {
                                            SignKey = accountKey
                                        };
                                        join.ToArray();
                                        serviceTransactions.Add(join);

                                        var ao = new AccountOperation(nextAccountId, accountKey.PublicKey, timestamp);
                                        ao.UpdateOperationId(nextTransactionId);

                                        coreOperations.Add(ao);
                                        accounts.Add(ao);

                                        nextTransactionId++;
                                        nextAccountId++;
                                    }

                                    blockStateOperation.AddBlockState(nextChainId, Protocol.GenesisBlockId, 0, 0, serviceTransactions.Count);
                                    serviceTransactionsList[nextChainId] = serviceTransactions;
                                }

                                nextChainId++;
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    Log.HandleException(ex, LogLevels.Error);
                }
            }

            coreOperations.Add(blockStateOperation);
            blockStateOperation.UpdateOperationId(nextTransactionId);
            blockStateOperation.AddBlockState(Protocol.CoreChainId, Protocol.GenesisBlockId, Protocol.GenesisBlockNetworkKeyIssuer, 0, nextTransactionId);

            var block = new CoreBlock(Protocol.GenesisBlockId, Protocol.GenesisBlockNetworkKeyIssuer, 0, timestamp, nextAccountId, nextChainId, Hash.Empty(Protocol.TransactionHashType), Hash.Empty(ValidationOperation.ValidationHashType), coreOperations, new List <CoreTransaction>());

            var signatures = new BlockSignatures(block);

            signatures.AddSignature(block.Issuer, block, networkKey);

            return(new GenesisBlockResult(block, signatures, networkKey.PublicKey, networkKeys[1].Store, networkKeys[1].Password, serviceTransactionsList));
        }
コード例 #16
0
 public RevenueMetaDiscStorage(Base.Storage storage, ChainType chainType, int chainId, uint chainIndex, string name) : base(storage, chainType, chainId, chainIndex, name, 1024, DiscStorageFlags.UnsortedDynamicIndex | DiscStorageFlags.AppendOnly, 64)
 {
 }
コード例 #17
0
ファイル: ServiceHost.cs プロジェクト: HeleusCore/Heleus.Node
        public ServiceHost(Node.Node node, ServiceChain serviceChain, IReadOnlyDictionary <uint, DataChain> dataChains, MaintainChain maintainChain, Base.Storage storage, int chainId, string serviceName, string serviceSearchPath, string serviceConfigString)
        {
            ChainId = chainId;

            _node          = node;
            _serviceChain  = serviceChain;
            _dataChains    = dataChains;
            _maintainChain = maintainChain;

            var _serviceType = GetServiceType(storage, chainId, serviceName, serviceSearchPath);

            ServiceDataPath = $"servicedata/{chainId}/";
            storage.CreateDirectory(ServiceDataPath);
            FullServiceDataPath = Path.Combine(storage.Root.FullName, ServiceDataPath);

            _serviceConfigString = serviceConfigString;
            if (!string.IsNullOrEmpty(_serviceConfigString))
            {
                _serviceConfigString += ";";
            }
            else
            {
                _serviceConfigString = string.Empty;
            }

            _serviceConfigString += $"{Heleus.Service.ServiceHelper.ServiceDataPathKey}={FullServiceDataPath};";
            _serviceConfigString += $"{Heleus.Service.ServiceHelper.ServiceChainIdKey}={chainId};";

            try
            {
                _service = (IService)Activator.CreateInstance(_serviceType);
                if (_service != null)
                {
                    _service.Initalize(ServiceOptions);
                }
            }
            catch (Exception ex)
            {
                Log.Warn($"Creating service {_serviceType.Name} failed.", this);
                Log.HandleException(ex, this);
            }
        }