diff --git a/dkgNode/Program.cs b/dkgNode/Program.cs index 19ee751..aabc05e 100644 --- a/dkgNode/Program.cs +++ b/dkgNode/Program.cs @@ -25,50 +25,61 @@ using dkgNode.Models; using dkgNode.Services; -using Microsoft.Extensions.Logging; -using Solnet.Wallet; -using Solnet.Wallet.Bip39; +using System.Text.Json; var builder = Host.CreateApplicationBuilder(args); + +// Set up configuration sources +var configuration = new ConfigurationBuilder() + .SetBasePath(Directory.GetCurrentDirectory()) + .AddJsonFile("appsettings.json", optional: false, reloadOnChange: false) + .AddEnvironmentVariables() + .Build(); + +builder.Services.AddSingleton(configuration); + builder.Services.AddHostedService(serviceProvider => { var logger = serviceProvider.GetRequiredService>(); - string? ps = Environment.GetEnvironmentVariable("DKG_NODE_POLLING_INTERVAL"); - int pollingInterval = 3000; - if (ps != null) - { - try - { - pollingInterval = int.Parse(ps); - } - catch - { - logger.LogWarning("DKG_NODE_POLLING_INTERVAL must be an integer, got {ps}", ps); - } - } - string? address = Environment.GetEnvironmentVariable("DKG_NODE_SOLANA_ADDRESS"); - if (address is null) - { - string? mnemonic; - (address, mnemonic) = DkgNodeConfig.GenerateNewAddress(); - logger.LogWarning("**** Creating solana wallet, please use it for testing only ****\nSolana Address: {solanaAddress}\nMnemonic: {mnemonic}", address, mnemonic); - } - else + var configSection = configuration.GetSection("Node"); + int pollingInterval = configSection.GetValue("PollingInterval", configuration.GetValue("DKG_NODE_POLLING_INTERVAL") ?? 5000); + + string serviceNodeUrlDefault = configuration.GetValue("DKG_SERVICE_NODE_URL") ?? "https://localhost:8081"; + string serviceNodeUrl = configSection.GetValue("ServiceNodeUrl") ?? serviceNodeUrlDefault; + + string? niceName = configSection.GetValue("Name", configuration.GetValue("DKG_NODE_NAME")); + + string? keyStoreDefault = configuration.GetValue("DKG_SOLANA_KEYSTORE"); + string? keyStore = configSection.GetValue("KeyStore") ?? keyStoreDefault; + + string keyStorePwdDefault = configuration.GetValue("DKG_SOLANA_KEYSTORE_PWD") ?? ""; + string keyStorePwd = configSection.GetValue("KeyStorePwd") ?? keyStorePwdDefault; + + string? solanaAddress = null; + string? solanaPrivateKey = null; + + string? newKeyStore; + + (solanaAddress, solanaPrivateKey, newKeyStore) = KeyStoreService.DecodeOrCreate(keyStore, keyStorePwd, logger); + + if (newKeyStore is not null) { - logger.LogInformation("Using Solana Address: {solanaAddress}", address); + KeyStoreService.UpdateAppsettingsJson(newKeyStore, logger); } var config = new DkgNodeConfig() { - NiceName = Environment.GetEnvironmentVariable("DKG_NODE_NAME"), + NiceName = niceName, PollingInterval = pollingInterval, - ServiceNodeUrl = Environment.GetEnvironmentVariable("DKG_SERVICE_NODE_URL") ?? "https://localhost:8081", - Address = address + ServiceNodeUrl = serviceNodeUrl, + Address = solanaAddress }; - string? dieOnStep2 = Environment.GetEnvironmentVariable("DKG_NODE_DIE_ON_STEP_TWO"); - string? dieOnStep3 = Environment.GetEnvironmentVariable("DKG_NODE_DIE_ON_STEP_THREE"); + // These are for testing purposes only + // Use environment variables, appsettings.json won't work + string? dieOnStep2 = configuration.GetValue("DKG_NODE_DIE_ON_STEP_TWO"); + string? dieOnStep3 = configuration.GetValue("DKG_NODE_DIE_ON_STEP_THREE"); return new dkgNode.DkgNodeWorker(config, logger, dieOnStep2 != null, dieOnStep3 != null); }); diff --git a/dkgNode/Services/KeyStoreService.cs b/dkgNode/Services/KeyStoreService.cs new file mode 100644 index 0000000..7bf4360 --- /dev/null +++ b/dkgNode/Services/KeyStoreService.cs @@ -0,0 +1,124 @@ +using Solnet.KeyStore.Model; +using Solnet.KeyStore; +using Solnet.Wallet.Bip39; +using Solnet.Wallet; +using System.Text; +using System.Text.Json; + +namespace dkgNode.Services +{ + public static class KeyStoreService + { + public static (string, string, string?) DecodeOrCreate(string? keyStore, string keyStorePwd, ILogger logger) + { + string? solanaAddress = null; + string? solanaPrivateKey = null; + + byte[] keyStoreDataBytes; + string keyStoreString; + + string? newKeyStore = null; + + var secretKeyStoreService = new SecretKeyStoreService(); + + if (keyStore is not null) + { + try + { + + keyStoreDataBytes = Convert.FromBase64String(keyStore); + keyStoreString = Encoding.UTF8.GetString(keyStoreDataBytes); + + JsonDocument jsonDocument = JsonDocument.Parse(keyStoreString); + solanaAddress = jsonDocument.RootElement.GetProperty("address").GetString(); + + if (solanaAddress is null) + { + logger.LogWarning("Failed to determine solana address from key store, creating a new one."); + } + else + { + keyStoreDataBytes = secretKeyStoreService.DecryptKeyStoreFromJson(keyStorePwd, keyStoreString); + solanaPrivateKey = Encoding.UTF8.GetString(keyStoreDataBytes); + logger.LogInformation("Using Solana Address: {solanaAddress}", solanaAddress); + } + } + catch (Exception ex) + { + logger.LogWarning("Failed to decode key store, creating a new one.\n{msg}", ex.Message); + } + } + + if (solanaAddress is null || solanaPrivateKey is null) + { + var mnemonic = new Mnemonic(WordList.English, WordCount.Twelve); + var wallet = new Wallet(mnemonic); + + Account account = wallet.Account; + + // The public key of the account is the Solana address + solanaAddress = account.PublicKey.Key; + solanaPrivateKey = account.PrivateKey.Key; + logger.LogWarning("**** Created solana account, please use it for testing only ****\nMnemonic: {mnemonic}\nAddress: {solanaAddress}\nPrivate key: {solanaPrivateKey}", + mnemonic, + solanaAddress, + solanaPrivateKey); + + keyStoreDataBytes = Encoding.UTF8.GetBytes(solanaPrivateKey); + keyStoreString = secretKeyStoreService.EncryptAndGenerateDefaultKeyStoreAsJson("", keyStoreDataBytes, solanaAddress); + keyStoreDataBytes = Encoding.UTF8.GetBytes(keyStoreString); + keyStoreString = Convert.ToBase64String(keyStoreDataBytes); + newKeyStore = keyStoreString; + } + + return (solanaAddress, solanaPrivateKey, newKeyStore); + } + + public static void UpdateAppsettingsJson(string newKeyStore, ILogger logger) + { + try + { + const string appSettingsPath = "appsettings.json"; + const string nodeSectionName = "Node"; + const string keyStorePropertyName = "KeyStore"; + + var json = File.ReadAllText(appSettingsPath); + using var doc = JsonDocument.Parse(json); + var root = doc.RootElement.Clone(); + + var cfg = JsonSerializer.Deserialize>(root.GetRawText()); + + if (cfg is not null) + { + Dictionary nodeSection; + + if (cfg.TryGetValue(nodeSectionName, out object? nodeSectionObj) && nodeSectionObj is JsonElement nodeSectionElement) + { + nodeSection = JsonSerializer.Deserialize>(nodeSectionElement.GetRawText()) ?? new Dictionary(); + } + else + { + nodeSection = new Dictionary(); + } + + nodeSection[keyStorePropertyName] = newKeyStore; + var nodeSectionJson = JsonSerializer.Serialize(nodeSection, new JsonSerializerOptions { WriteIndented = true }); + cfg[nodeSectionName] = JsonSerializer.Deserialize(nodeSectionJson); + + var modifiedJson = JsonSerializer.Serialize(cfg, new JsonSerializerOptions { WriteIndented = true }); + File.WriteAllText(appSettingsPath, modifiedJson); + logger.LogInformation("Saved key store to {appSettingsPath}:\n{keyStoreString}", appSettingsPath, newKeyStore); + } + else + { + logger.LogWarning("Failed to save key store: configuration is null."); + } + } + catch (Exception ex) + { + logger.LogWarning("Failed to save key store:\n{msg}", ex.Message); + } + + } + } +} diff --git a/dkgNode/appsettings.json b/dkgNode/appsettings.json index d8daaee..23ef0d5 100644 --- a/dkgNode/appsettings.json +++ b/dkgNode/appsettings.json @@ -4,7 +4,8 @@ "Default": "Information", "Microsoft.Hosting.Lifetime": "Information", "Microsoft.EntityFrameworkCore": "Information" - } + }, + "Node": { } -} +} \ No newline at end of file diff --git a/dkgNode/dkgNode.csproj b/dkgNode/dkgNode.csproj index d1280c8..df4a6c1 100644 --- a/dkgNode/dkgNode.csproj +++ b/dkgNode/dkgNode.csproj @@ -13,7 +13,9 @@ + + diff --git a/dkgNodeLibrary/Models/DkgNodeConfig.cs b/dkgNodeLibrary/Models/DkgNodeConfig.cs index 1ad84c7..496fee3 100644 --- a/dkgNodeLibrary/Models/DkgNodeConfig.cs +++ b/dkgNodeLibrary/Models/DkgNodeConfig.cs @@ -81,19 +81,6 @@ public DkgNodeConfig(DkgNodeConfig other) PollingInterval = other.PollingInterval; ServiceNodeUrl = other.ServiceNodeUrl; } - - public static (string, string) GenerateNewAddress() - { - var mnemonic = new Mnemonic(WordList.English, WordCount.Twelve); - var wallet = new Wallet(mnemonic); - Account account = wallet.Account; - - // The public key of the account is the Solana address - string solanaAddress = account.PublicKey.Key; - - return (solanaAddress, mnemonic.ToString()); - } - } } diff --git a/dkgServiceNode/Controllers/NodesController.cs b/dkgServiceNode/Controllers/NodesController.cs index 0b5cad7..ff51fe6 100644 --- a/dkgServiceNode/Controllers/NodesController.cs +++ b/dkgServiceNode/Controllers/NodesController.cs @@ -326,9 +326,7 @@ internal async Task AcceptFailed(Round? round, Node node, StatusRe [ProducesResponseType(StatusCodes.Status409Conflict, Type = typeof(ErrMessage))] public async Task> Status(StatusReport statusReport) { - // А это мой любимый автомат Мили ... центр любой системы :) - Dictionary<(RStatus?, NStatus), Func>> actionMap = - new Dictionary<(RStatus?, NStatus), Func>>() + var actionMap = new Dictionary<(RStatus?, NStatus), Func>>() { { (null, NStatus.NotRegistered), Accept }, { (RStatus.NotStarted, NStatus.NotRegistered), WrongStatus }, diff --git a/dkgServiceNode/Data/DbEnsure.cs b/dkgServiceNode/Data/DbEnsure.cs index 10a6390..fd81bbe 100644 --- a/dkgServiceNode/Data/DbEnsure.cs +++ b/dkgServiceNode/Data/DbEnsure.cs @@ -150,13 +150,15 @@ private static bool VCheck(string v, NpgsqlConnection connection) return (rows != null && (long)rows != 0); } - public static void Ensure_0_8_0(NpgsqlConnection connection) + public static int Ensure_0_8_0(NpgsqlConnection connection) { // Check if table 'versions' exists var sql = "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'versions';"; var command = new NpgsqlCommand(sql, connection); var rows = command.ExecuteScalar(); + int r = 0; + if (rows != null && (long)rows != 0) { sql = "SELECT COUNT(*) FROM versions WHERE version = '0.8.0';"; @@ -167,8 +169,10 @@ public static void Ensure_0_8_0(NpgsqlConnection connection) if (rows == null || (long)rows == 0) { var scriptCommand = new NpgsqlCommand(sqlScript_0_8_0, connection); - int r = scriptCommand.ExecuteNonQuery(); + r = scriptCommand.ExecuteNonQuery(); } + + return r; } private static void PuVersionUpdate(string v, NpgsqlConnection connection) { diff --git a/dkgServiceNode/Dockerfile b/dkgServiceNode/Dockerfile index 614b989..a9fcbc8 100644 --- a/dkgServiceNode/Dockerfile +++ b/dkgServiceNode/Dockerfile @@ -20,4 +20,5 @@ RUN dotnet publish "./dkgServiceNode.csproj" -c $BUILD_CONFIGURATION -o /app/pub FROM base AS final WORKDIR /app COPY --from=publish /app/publish . +RUN chmod -R 777 /app ENTRYPOINT ["dotnet", "dkgServiceNode.dll"] \ No newline at end of file diff --git a/dkgServiceNode/Models/Node.cs b/dkgServiceNode/Models/Node.cs index fba4c0c..54cb376 100644 --- a/dkgServiceNode/Models/Node.cs +++ b/dkgServiceNode/Models/Node.cs @@ -60,6 +60,9 @@ public class Node [NotMapped] public int? PrevRandom { get; set; } + [NotMapped] + public string Signature { get; set; } = string.Empty; + [ForeignKey("RoundId")] public Round? Round{ get; set; } diff --git a/docker-compose.yml b/docker-compose.yml index 85502d2..64ba301 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -24,9 +24,8 @@ services: environment: - DKG_SERVICE_NODE_URL=http://dkg_service_node:8080 - DKG_NODE_NAME=First node - - DKG_NODE_POLLING_INTERVAL=3500 - # bonus pretty melt journey project siren harsh pioneer spin holiday chase harvest - - DKG_NODE_SOLANA_ADDRESS=4KFR297L24YnX9A232mQpprhCaJ4Y5CA57JFXCCHrjqS + # "decrease high inject kitchen alone train income charge hint gauge deal parrot" + - DKG_SOLANA_KEYSTORE=eyJjcnlwdG8iOnsiY2lwaGVyIjoiYWVzLTEyOC1jdHIiLCJjaXBoZXJ0ZXh0IjoiNDg3NWUwYzFhNmQ5YjY4MDdiYTY2NmY1YTFjYWE2NzgzMDEzZTFmYjUzODRhY2YwZDgzNTI1MWM3MjRlNGEwZGY3MGRjYzcwMTk4ZjA2NjI4MTI3ZDY5OGIzZTdlOTk2MWJmYTg2ZDg2OTg1OGEwMGVhODgzOTM5MjFlNDlkZmFiZjFkN2U1NGNhMjViNWEyMWRmNjVhYjQ2NWQ1YTg5NDc5NjA0Y2ExMjNmZjc0NTgiLCJjaXBoZXJwYXJhbXMiOnsiaXYiOiI5OWY4ZWE2NjU2OWNmNTI1YjE2NGE0MWM4YmIzZGMwYyJ9LCJrZGYiOiJzY3J5cHQiLCJtYWMiOiJmNDdiNjExMDZlMmNiMGNiM2IwZDNiYzQ3OThkMGY2YmIxOTExYmNmYWU1YTNkYTQwM2EwZDc5Yjg2ZTQxYTc4Iiwia2RmcGFyYW1zIjp7Im4iOjI2MjE0NCwiciI6MSwicCI6OCwiZGtsZW4iOjMyLCJzYWx0IjoiMTBmMTc5MGIyZjIwOGM3NTIyZGY1NTMxYTU0MTViYjdhMjNmYmIzMjE0MmY1NzQ3Y2FlM2Y4MDA0NGM0NzQ4OCJ9fSwiaWQiOiIwZjE2M2E2MC1jNjdmLTQxNGYtYjY1OC0xMDAyMjk1MTA0NTkiLCJhZGRyZXNzIjoiNWkzdkJwcDZuMkdSZHdGcnhVNmJ4U3lTWG41S2dyNDIyMkE0eGM1SzcyYUwiLCJ2ZXJzaW9uIjozfQ== build: context: . dockerfile: dkgNode/Dockerfile @@ -39,8 +38,8 @@ services: environment: - DKG_SERVICE_NODE_URL=http://dkg_service_node:8080 - DKG_NODE_NAME=Second node - # wild dizzy good quantum purpose crazy evidence oak give pass describe wild - - DKG_NODE_SOLANA_ADDRESS=AKoAnVhRtm7c35UMWZUVzktdD7Tq1nZpRVminmHwFER6 + # salon glove crisp couple bounce wool cube super casino warm census edit + - DKG_SOLANA_KEYSTORE=eyJjcnlwdG8iOnsiY2lwaGVyIjoiYWVzLTEyOC1jdHIiLCJjaXBoZXJ0ZXh0IjoiNDUwNDBjMGExZTkyMGU1ZmU0MDJlYzMyN2JkYjM4ZThjYzg3YWE3NGJmY2Q2OWFhYTM5M2UyZGIxNzRmOGM0OTU4ZDQ4OTlmY2Q4M2I4NjJjYmVmMjRlYThjNmMxM2IzZDEzOGVmNDhjY2EwYmM4ZTc5MmVlMDM2Y2I4ZTM1YjI0ODgyNDRlMDMzNWQ4ZmE4NjEyNTFjMTU4NDk4Yzk4MGY1NDM4OWYwYmRkNTAwODgiLCJjaXBoZXJwYXJhbXMiOnsiaXYiOiJmMmE0YjQ3NWY0MzZkOGY2MmRjOGNhODlmN2RlNjY0NCJ9LCJrZGYiOiJzY3J5cHQiLCJtYWMiOiI2YjAzMzZhYmQ4OTM3YjVmMTZkYzY2ZTg2MDlhZTM0NjgxNmU0MWI0NzExNmQ2OTNkNjQ4NWJkNGZiMTYxZDdkIiwia2RmcGFyYW1zIjp7Im4iOjI2MjE0NCwiciI6MSwicCI6OCwiZGtsZW4iOjMyLCJzYWx0IjoiZTljNGYzZmZlZmEzMDMwNDYxNzdlNGQ4YzQxMDdhY2Y3NTZkYTQ5NjdiYTNjZGJlOGZkMDRmYzA2YTY5OTk0ZSJ9fSwiaWQiOiI4YTgwYTkyYi01YTczLTQwMDEtODdjNC01ODViNTkzYWFhM2MiLCJhZGRyZXNzIjoiM3FVNGl4VFdQZXlrZFBGaXJ6bWJ1TThWM2tYblpINmd6WnhSanhVNUJxTTUiLCJ2ZXJzaW9uIjozfQ== build: context: . dockerfile: dkgNode/Dockerfile @@ -53,8 +52,8 @@ services: environment: - DKG_SERVICE_NODE_URL=http://dkg_service_node:8080 - DKG_NODE_NAME=Third node - # tail analyst dream tornado simple brown mad same small wagon mammal fun - - DKG_NODE_SOLANA_ADDRESS=EgcYjVC6wBoUx4gUspYDjiKCfV9WqfV5iTk3A9iuKi41 + # fruit kitten anchor reduce ticket drink sentence worth better orchard moral direct + - DKG_SOLANA_KEYSTORE=eyJjcnlwdG8iOnsiY2lwaGVyIjoiYWVzLTEyOC1jdHIiLCJjaXBoZXJ0ZXh0IjoiNmQxZmNiMzNjYTQ3Njg4ZWRiZDUwMTJiZmE0NGM5ZGQ1Mzk1NGE5OTI1ZjZjNzFkZTQ2NGFmOGEwYWZhNTE3N2M0ZDIzNTc3YWUxYTMxN2YyMzk1ODc5MzAwMWI5ZmVlNjVkZGRmZTI3NDljM2MzOGNhYTI1MzVhZDJhYTk5MmYwMjA4MzE3ZjVmMGRjODg1YjcyMjZkMWE4MmRlZWUzNmMyODZhNGJmM2RjMmEzIiwiY2lwaGVycGFyYW1zIjp7Iml2IjoiYmI4YmIxODdlNzk4OTQ3MDMzNGMwZWUzMTk4MDkyOTkifSwia2RmIjoic2NyeXB0IiwibWFjIjoiMDIzMmUyZDU0ODgxOWQyMjBlOTNjZGZjZDUyYWYyOWQwYzQ4ZTNmNDRmYTY5YzYzOWIwYTk1MDk3NmI2MmM1MSIsImtkZnBhcmFtcyI6eyJuIjoyNjIxNDQsInIiOjEsInAiOjgsImRrbGVuIjozMiwic2FsdCI6ImY2ODZkOGQwZmYwM2ZkMWU0NzE4MjJhN2RjZmU2MmU2ZmZlZjc1ODUzNDNkZjZhMDhmYTAwNDY1YWQ0OWU4ZmYifX0sImlkIjoiM2ZkZDJkODYtMzJjOC00NGNlLWJiYjgtM2Q0NWJiOWNjYjcwIiwiYWRkcmVzcyI6IjhTd3ROeG5hWnhHRGk1VVo0VlhudG9HQWNCTHlnb3ZCV0I0cktta25jQUhCIiwidmVyc2lvbiI6M30= build: context: . dockerfile: dkgNode/Dockerfile @@ -67,8 +66,8 @@ services: environment: - DKG_SERVICE_NODE_URL=http://dkg_service_node:8080 - DKG_NODE_NAME=Fourth node - # ramp marble that cactus fee field shadow brand just father light sport - - DKG_NODE_SOLANA_ADDRESS=8iVGKCdSkzyrnLKzeGnbJYSfQsdV2NsdyzQkTDq3YvfV + # ribbon pistol ranch icon scorpion later fruit lab affair wheel credit camp + - DKG_SOLANA_KEYSTORE=eyJjcnlwdG8iOnsiY2lwaGVyIjoiYWVzLTEyOC1jdHIiLCJjaXBoZXJ0ZXh0IjoiNGY0MmUxYWMxMGM5ODc5YjhlZDRiZTE0Zjk5YzE4ODljODA4MjY0Y2QzZjM2MjY0NWZkMTQ3ZjU5NGZmODU2MDIyYzU2NTRkNGI0OTQyOWI0YWRkMWY0MDU1M2RlNzRhYmM4MjU4NWFmMDA4NmIxMDMxZjMxOWJmYWM2YzQ3YWZjNmQ5MWY4ODZiZWY5ZTIyMmVmMTk2NjgwZTIyYTU3Yjk0NTI3ZDgyMTE1ZGM3N2UiLCJjaXBoZXJwYXJhbXMiOnsiaXYiOiI4ODY4MjE5OTBlMzc2ZThjOTlmNWUwYTQ2YmYzZjRlYyJ9LCJrZGYiOiJzY3J5cHQiLCJtYWMiOiIzYjBlMjc1MDczNTU4NDlkYWRmYTc0MDg3OWM3Mzg2NjZjODM1NGYzMmY1YjI2ODMyNWIyNThkZjYyNjRjNWQ3Iiwia2RmcGFyYW1zIjp7Im4iOjI2MjE0NCwiciI6MSwicCI6OCwiZGtsZW4iOjMyLCJzYWx0IjoiODlkMDAzMTZiODMzZTk5ZjU4OTI0NGMwZDNhYTY4MTgxMTkwMmNlMDJiNGFlMThiNzRkODc4MzdhMDkxMjBlZSJ9fSwiaWQiOiJkMzZlM2YyMy05YTEzLTQ3Y2QtODgwYy0xODNiNmMwNjUzYWUiLCJhZGRyZXNzIjoiQmVCTVYzemlrRUp4UFpFaUxBb2syQm5CUHZGUUNhdXphS1hHdjE5OW9XSmkiLCJ2ZXJzaW9uIjozfQ== build: context: . dockerfile: dkgNode/Dockerfile @@ -81,7 +80,9 @@ services: environment: - DKG_SERVICE_NODE_URL=http://dkg_service_node:8080 - DKG_NODE_NAME=Fifth node - - DKG_NODE_DIE_ON_STEP_TWO=Yes + # DKG_NODE_DIE_ON_STEP_TWO=Yes + # pave recipe charge leave response join peasant timber resemble motion own crop + - DKG_SOLANA_KEYSTORE=eyJjcnlwdG8iOnsiY2lwaGVyIjoiYWVzLTEyOC1jdHIiLCJjaXBoZXJ0ZXh0IjoiNzUyMWU2MTYzZTQ0NDNlMWIxYTg1NzI3NGIxMTM5YmY2OWYwZGJmYmIzOWJlNTQwODE2ZDcwOGQwMzYyNTU1YTZiMjQzZjBmNGUyNDJkMGRmOGI1YWIwNzI0NWE5ZDgyZWYzMzc5NjA4NDFmN2Q2MzcwNjAxNDJlNzBkOWUzMzNlZWU3ZGI5MGY0Yzk1ZDYxZGI3Mzg0MDJjOWMwNGJmOGE1OTlkMWRiNDc1YjBlZTAiLCJjaXBoZXJwYXJhbXMiOnsiaXYiOiI0M2I0MmNmNzk5M2RmMWQzYzhiMTQ3N2ZhMzFhN2FhZSJ9LCJrZGYiOiJzY3J5cHQiLCJtYWMiOiJkMjU3NThiYWIwNGRkZWM4ZWIwYTE0MjFmMDUzZWEyODgxM2Q0ZGNmOGRkYmJmNGYzNGQ3NThlODgxYWEwZTYzIiwia2RmcGFyYW1zIjp7Im4iOjI2MjE0NCwiciI6MSwicCI6OCwiZGtsZW4iOjMyLCJzYWx0IjoiNTE3NDgxMGZjM2JlYmZjZDJmYzM1MDVlZGJlZjgwMTI5YjcwYjk1OTAxNDFlNDdiODFhMzIzOTZjYThhYzE3MyJ9fSwiaWQiOiIzYTMyMWMyMy1hYTg3LTQ1NjAtYmRkZC01YzZmMTE2NWYxMDQiLCJhZGRyZXNzIjoiQkFwakg0RG9HNUV3VkFlQlprbmFFM0xFR0RFa0tnY3U1TVhOeWpSazJBM3ciLCJ2ZXJzaW9uIjozfQ== build: context: . dockerfile: dkgNode/Dockerfile @@ -97,7 +98,7 @@ services: - POSTGRES_PASSWORD=postgres - POSTGRES_DB=dkgservice volumes: - - pgdata:/var/lib/postgresql + - pgdata:/var/lib/postgresqlc adminer: container_name: adminer