diff --git a/src/Nethermind/Directory.Packages.props b/src/Nethermind/Directory.Packages.props index b7fae1de28d..21ac26de7c4 100644 --- a/src/Nethermind/Directory.Packages.props +++ b/src/Nethermind/Directory.Packages.props @@ -54,7 +54,8 @@ - + + diff --git a/src/Nethermind/Nethermind.Runner/configs/chiado.cfg b/src/Nethermind/Nethermind.Runner/configs/chiado.cfg index 1dc33ff7a65..ea1634e1b24 100644 --- a/src/Nethermind/Nethermind.Runner/configs/chiado.cfg +++ b/src/Nethermind/Nethermind.Runner/configs/chiado.cfg @@ -32,16 +32,13 @@ "ForceSealing": true }, "Shutter": { - "ValidatorRegistryContractAddress": "0xa9289A3Dd14FEBe10611119bE81E5d35eAaC3084", "SequencerContractAddress": "0x2aD8E2feB0ED5b2EC8e700edB725f120576994ed", + "ValidatorRegistryContractAddress": "0xa9289A3Dd14FEBe10611119bE81E5d35eAaC3084", "KeyBroadcastContractAddress": "0x9D31865BEffcE842FBd36CDA587aDDA8bef804B7", "KeyperSetManagerContractAddress": "0xC4DE9FAf4ec882b33dA0162CBE628B0D8205D0c0", "BootnodeP2PAddresses": [ - "/ip4/157.230.104.246/tcp/23003/p2p/12D3KooWFUYoPd3bdPuRi6FXkEQRSw7FRf2e23NAypjfDVYuvBAV", - "/ip4/134.209.225.234/tcp/23003/p2p/12D3KooWAsBKAj1NEtvu7wcLiEVU49N6Z9GPK3tZ87m17tFdWdNE", - "/ip4/157.230.114.117/tcp/23003/p2p/12D3KooWEDk8XJdxHjCHh9wTGVRXtpyCvCP4N4Jztr8zTJd4rMVX", - "/ip4/64.225.104.2/tcp/23003/p2p/12D3KooWMXTYrwEz4v5aGa7chYHjVVpjzzkq9JSjZzxbdh9YgAQS", - "/ip4/157.230.111.142/tcp/23003/p2p/12D3KooWA3FPqxV8whaFPbLzwbyDEWML4y73D6RJqb2mn7SHz6fg" + "/ip4/167.99.177.227/tcp/23005/p2p/12D3KooWSdm5guPBdn8DSaBphVBzUUgPLg9sZLnazEUrcbtLy254", + "/ip4/159.89.15.119/tcp/23005/p2p/12D3KooWPP6bp2PJQR8rUvG1SD4qNH4WFrKve6DMgWThyKxwNbbH" ], "InstanceID": "102000" }, diff --git a/src/Nethermind/Nethermind.Runner/configs/gnosis.cfg b/src/Nethermind/Nethermind.Runner/configs/gnosis.cfg index e98e44b71a9..768621bd8d7 100644 --- a/src/Nethermind/Nethermind.Runner/configs/gnosis.cfg +++ b/src/Nethermind/Nethermind.Runner/configs/gnosis.cfg @@ -24,6 +24,17 @@ "BlockProductionTimeoutMs": 3000, "TargetBlockGasLimit": 17000000 }, + "Shutter": { + "SequencerContractAddress": "0x2aD8E2feB00xc5C4b277277A1A8401E0F039dfC49151bA64DC2ED5b2EC8e700edB725f120576994ed", + "ValidatorRegistryContractAddress": "0xefCC23E71f6bA9B22C4D28F7588141d44496A6D6", + "KeyBroadcastContractAddress": "0x626dB87f9a9aC47070016A50e802dd5974341301", + "KeyperSetManagerContractAddress": "0x7C2337f9bFce19d8970661DA50dE8DD7d3D34abb", + "BootnodeP2PAddresses": [ + "/ip4/167.99.177.227/tcp/23003/p2p/12D3KooWD35AESYCttDEi3J5WnQdTFuM5JNtmuXEb1x4eQ28gb1s", + "/ip4/159.89.15.119/tcp/23003/p2p/12D3KooWRzAhgPA16DiBQhiuYoasYzJaQSAbtc5i5FvgTi9ZDQtS" + ], + "InstanceID": "1000" + }, "Mining": { "MinGasPrice": "1000000000" }, diff --git a/src/Nethermind/Nethermind.Shutter.Test/ShutterApiSimulator.cs b/src/Nethermind/Nethermind.Shutter.Test/ShutterApiSimulator.cs index c1709d2879c..8f8d8ceb00c 100644 --- a/src/Nethermind/Nethermind.Shutter.Test/ShutterApiSimulator.cs +++ b/src/Nethermind/Nethermind.Shutter.Test/ShutterApiSimulator.cs @@ -3,7 +3,9 @@ using System; using System.Collections.Generic; +using System.IO.Abstractions; using System.Linq; +using System.Net; using System.Threading.Tasks; using Nethermind.Abi; using Nethermind.Blockchain; @@ -14,6 +16,7 @@ using Nethermind.Core.Test.Builders; using Nethermind.Crypto; using Nethermind.Facade.Find; +using Nethermind.KeyStore.Config; using Nethermind.Logging; using Nethermind.Shutter.Config; using Nethermind.State; @@ -32,11 +35,14 @@ public class ShutterApiSimulator( ISpecProvider specProvider, ITimestamper timestamper, IWorldStateManager worldStateManager, + IFileSystem fileSystem, + IKeyStoreConfig keyStoreConfig, IShutterConfig cfg, Dictionary validatorsInfo, Random rnd ) : ShutterApi(abiEncoder, blockTree, ecdsa, logFinder, receiptStorage, - logManager, specProvider, timestamper, worldStateManager, cfg, validatorsInfo, ShutterTestsCommon.SlotLength) + logManager, specProvider, timestamper, worldStateManager, fileSystem, + keyStoreConfig, cfg, validatorsInfo, ShutterTestsCommon.SlotLength, IPAddress.None) { public int EonUpdateCalled = 0; public int KeysValidated = 0; @@ -110,7 +116,7 @@ protected override async Task OnKeysReceived(Dto.DecryptionKeys decryptionKeys) // fake out P2P module - protected override void InitP2P(IShutterConfig cfg, ILogManager logManager) + protected override void InitP2P(IPAddress _) { P2P = Substitute.For(); } diff --git a/src/Nethermind/Nethermind.Shutter.Test/ShutterTestsCommon.cs b/src/Nethermind/Nethermind.Shutter.Test/ShutterTestsCommon.cs index 03b157963df..612414beca8 100644 --- a/src/Nethermind/Nethermind.Shutter.Test/ShutterTestsCommon.cs +++ b/src/Nethermind/Nethermind.Shutter.Test/ShutterTestsCommon.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using System.IO.Abstractions; using Nethermind.Abi; using Nethermind.Blockchain; using Nethermind.Blockchain.Receipts; @@ -11,6 +12,7 @@ using Nethermind.Core.Specs; using Nethermind.Crypto; using Nethermind.Facade.Find; +using Nethermind.KeyStore.Config; using Nethermind.Logging; using Nethermind.Shutter.Config; using Nethermind.Specs; @@ -56,7 +58,8 @@ public static ShutterApiSimulator InitApi(Random rnd, ITimestamper? timestamper eventSimulator ?? InitEventSimulator(rnd), AbiEncoder, blockTree, Ecdsa, logFinder, receiptStorage, LogManager, SpecProvider, timestamper ?? Substitute.For(), - worldStateManager, Cfg, [], rnd + worldStateManager, Substitute.For(), + Substitute.For(), Cfg, [], rnd ); } @@ -64,7 +67,8 @@ public static ShutterApiSimulator InitApi(Random rnd, MergeTestBlockchain chain, => new( eventSimulator ?? InitEventSimulator(rnd), AbiEncoder, chain.BlockTree.AsReadOnly(), chain.EthereumEcdsa, chain.LogFinder, chain.ReceiptStorage, - chain.LogManager, chain.SpecProvider, timestamper ?? chain.Timestamper, chain.WorldStateManager, Cfg, [], rnd + chain.LogManager, chain.SpecProvider, timestamper ?? chain.Timestamper, chain.WorldStateManager, + Substitute.For(), Substitute.For(), Cfg, [], rnd ); public static ShutterEventSimulator InitEventSimulator(Random rnd) diff --git a/src/Nethermind/Nethermind.Shutter/Config/IShutterConfig.cs b/src/Nethermind/Nethermind.Shutter/Config/IShutterConfig.cs index 7bc477ae4c8..f96b1b8c0dc 100644 --- a/src/Nethermind/Nethermind.Shutter/Config/IShutterConfig.cs +++ b/src/Nethermind/Nethermind.Shutter/Config/IShutterConfig.cs @@ -3,6 +3,7 @@ using System; using System.IO; +using System.Linq; using Multiformats.Address; using Nethermind.Config; using Nethermind.Core; @@ -11,15 +12,6 @@ namespace Nethermind.Shutter.Config; public interface IShutterConfig : IConfig { - // todo: replace with bootnodes when peer discovery added - private const string DefaultP2PAddresses = -@"/ip4/139.59.130.109/tcp/23003/p2p/12D3KooWRZoofMsnpsjkgvfPQUyGXZQnn7EVnb4tw4ghNfwMnnsj, -/ip4/167.71.169.248/tcp/23003/p2p/12D3KooWGH3VxoSQXZ6wUuCmsv5caGQnhwfGejbkXH6uS2r7sehA, -/ip4/139.59.130.109/tcp/23003/p2p/12D3KooWNxTiw7CvD1fuyye5P8qPhKTTrRBW6wwZwMdqdTxjYF2H, -/ip4/178.128.192.239/tcp/23003/p2p/12D3KooWCdpkipTiuzVMfkV7yLLgqbFeAL8WmEP78hCoBGBYLugN, -/ip4/45.55.192.248/tcp/23003/p2p/12D3KooWMPuubKqksfMxvLwEBDScaopTdvPLr5J5SMmBEo2zkcMz, -/ip4/178.128.126.237/tcp/23003/p2p/12D3KooWAg1pGUDAfFWSZftpN3JjBfLUCGLQcZApJHv2VntdMS9U"; - [ConfigItem(Description = "Whether to enable Shutter.", DefaultValue = "false")] bool Enabled { get; set; } @@ -28,27 +20,27 @@ public interface IShutterConfig : IConfig string? ValidatorInfoFile { get; set; } [ConfigItem(Description = "The address of the Shutter sequencer contract.", - DefaultValue = "0xc5C4b277277A1A8401E0F039dfC49151bA64DC2E")] + DefaultValue = "null")] string? SequencerContractAddress { get; set; } [ConfigItem(Description = "The address of the Shutter validator registry contract.", - DefaultValue = "0xefCC23E71f6bA9B22C4D28F7588141d44496A6D6")] + DefaultValue = "null")] string? ValidatorRegistryContractAddress { get; set; } [ConfigItem(Description = "The address of the Shutter key broadcast contract.", - DefaultValue = "0x626dB87f9a9aC47070016A50e802dd5974341301")] + DefaultValue = "null")] string? KeyBroadcastContractAddress { get; set; } [ConfigItem(Description = "The address of the Shutter keyper set manager contract.", - DefaultValue = "0x7C2337f9bFce19d8970661DA50dE8DD7d3D34abb")] + DefaultValue = "null")] string? KeyperSetManagerContractAddress { get; set; } [ConfigItem(Description = "The p2p addresses of the Shutter Keyper network bootnodes.", - DefaultValue = DefaultP2PAddresses)] + DefaultValue = null)] string[]? BootnodeP2PAddresses { get; set; } [ConfigItem(Description = "Instance ID of Shutter keyper set.", - DefaultValue = "1000")] + DefaultValue = "0")] ulong InstanceID { get; set; } [ConfigItem(Description = "The port to connect to Shutter P2P network with.", @@ -64,6 +56,9 @@ public interface IShutterConfig : IConfig HiddenFromDocs = true)] string? P2PAgentVersion { get; set; } + [ConfigItem(Description = "The filename to use for the Shutter P2P key. If this not specified, the key is autogenerated in `shutter.key.plain` file.")] + string ShutterKeyFile { get; set; } + [ConfigItem(Description = "The Shutter validator registry message version.", DefaultValue = "0", HiddenFromDocs = true)] ulong ValidatorRegistryMessageVersion { get; set; } @@ -80,7 +75,7 @@ public interface IShutterConfig : IConfig DefaultValue = "true", HiddenFromDocs = true)] bool Validator { get; set; } - public void Validate() + public void Validate(out Multiaddress[] bootnodeP2PAddresses) { if (Validator && ValidatorInfoFile is null) { @@ -127,16 +122,13 @@ public void Validate() throw new ArgumentNullException(nameof(BootnodeP2PAddresses)); } - foreach (string addr in BootnodeP2PAddresses) + try + { + bootnodeP2PAddresses = BootnodeP2PAddresses.Select(addr => Multiaddress.Decode(addr)).ToArray(); + } + catch (NotSupportedException e) { - try - { - Multiaddress.Decode(addr); - } - catch (NotSupportedException) - { - throw new ArgumentException($"Could not decode Shutter keyper p2p address \"{addr}\"."); - } + throw new ArgumentException($"Could not decode Shutter bootnode p2p addresses.", e); } } } diff --git a/src/Nethermind/Nethermind.Shutter/Config/ShutterConfig.cs b/src/Nethermind/Nethermind.Shutter/Config/ShutterConfig.cs index 1e0e9c662f3..a8ed781e0a8 100644 --- a/src/Nethermind/Nethermind.Shutter/Config/ShutterConfig.cs +++ b/src/Nethermind/Nethermind.Shutter/Config/ShutterConfig.cs @@ -16,6 +16,7 @@ public class ShutterConfig : IShutterConfig public string? ValidatorInfoFile { get; set; } public string? P2PProtocolVersion { get; set; } = "/shutter/0.1.0"; public string? P2PAgentVersion { get; set; } = "github.com/shutter-network/rolling-shutter/rolling-shutter"; + public string ShutterKeyFile { get; set; } = "shutter.key.plain"; public ulong ValidatorRegistryMessageVersion { get; set; } = 0; public ulong InstanceID { get; set; } = 0; public int EncryptedGasLimit { get; set; } = 10000000; diff --git a/src/Nethermind/Nethermind.Shutter/IShutterApi.cs b/src/Nethermind/Nethermind.Shutter/IShutterApi.cs index c6ed5544372..4fff37c21bf 100644 --- a/src/Nethermind/Nethermind.Shutter/IShutterApi.cs +++ b/src/Nethermind/Nethermind.Shutter/IShutterApi.cs @@ -3,6 +3,7 @@ using System.Threading; using System.Threading.Tasks; +using Multiformats.Address; using Nethermind.Consensus; namespace Nethermind.Shutter; @@ -10,7 +11,7 @@ namespace Nethermind.Shutter; public interface IShutterApi { ShutterTxSource TxSource { get; } - Task StartP2P(CancellationTokenSource? cancellationTokenSource = null); + Task StartP2P(Multiaddress[] bootnodeP2PAddresses, CancellationTokenSource? cancellationTokenSource = null); ShutterBlockImprovementContextFactory GetBlockImprovementContextFactory(IBlockProducer blockProducer); ValueTask DisposeAsync(); } diff --git a/src/Nethermind/Nethermind.Shutter/IShutterP2P.cs b/src/Nethermind/Nethermind.Shutter/IShutterP2P.cs index 43f6bdb38e1..d72baa359c4 100644 --- a/src/Nethermind/Nethermind.Shutter/IShutterP2P.cs +++ b/src/Nethermind/Nethermind.Shutter/IShutterP2P.cs @@ -4,11 +4,12 @@ using System; using System.Threading; using System.Threading.Tasks; +using Multiformats.Address; namespace Nethermind.Shutter; public interface IShutterP2P { - Task Start(Func onKeysReceived, CancellationTokenSource? cts = null); + Task Start(Multiaddress[] bootnodeP2PAddresses, Func onKeysReceived, CancellationTokenSource? cts = null); ValueTask DisposeAsync(); } diff --git a/src/Nethermind/Nethermind.Shutter/Nethermind.Shutter.csproj b/src/Nethermind/Nethermind.Shutter/Nethermind.Shutter.csproj index 5f7acfe37b8..63efbd0fa08 100644 --- a/src/Nethermind/Nethermind.Shutter/Nethermind.Shutter.csproj +++ b/src/Nethermind/Nethermind.Shutter/Nethermind.Shutter.csproj @@ -31,6 +31,7 @@ + diff --git a/src/Nethermind/Nethermind.Shutter/ShutterApi.cs b/src/Nethermind/Nethermind.Shutter/ShutterApi.cs index 91b53f6a17d..7c87a7bf7a7 100644 --- a/src/Nethermind/Nethermind.Shutter/ShutterApi.cs +++ b/src/Nethermind/Nethermind.Shutter/ShutterApi.cs @@ -3,8 +3,11 @@ using System; using System.Collections.Generic; +using System.IO.Abstractions; +using System.Net; using System.Threading; using System.Threading.Tasks; +using Multiformats.Address; using Nethermind.Abi; using Nethermind.Blockchain; using Nethermind.Blockchain.Find; @@ -15,6 +18,7 @@ using Nethermind.Core.Specs; using Nethermind.Crypto; using Nethermind.Facade.Find; +using Nethermind.KeyStore.Config; using Nethermind.Logging; using Nethermind.Shutter.Config; using Nethermind.State; @@ -41,6 +45,8 @@ public class ShutterApi : IShutterApi private readonly ReadOnlyTxProcessingEnvFactory _txProcessingEnvFactory; private readonly IAbiEncoder _abiEncoder; private readonly ILogManager _logManager; + private readonly IFileSystem _fileSystem; + private readonly IKeyStoreConfig _keyStoreConfig; private readonly IShutterConfig _cfg; private readonly TimeSpan _blockWaitCutoff; @@ -54,9 +60,12 @@ public ShutterApi( ISpecProvider specProvider, ITimestamper timestamper, IWorldStateManager worldStateManager, + IFileSystem fileSystem, + IKeyStoreConfig keyStoreConfig, IShutterConfig cfg, Dictionary validatorsInfo, - TimeSpan slotLength + TimeSpan slotLength, + IPAddress ip ) { _cfg = cfg; @@ -65,6 +74,8 @@ TimeSpan slotLength _abiEncoder = abiEncoder; _logManager = logManager; _slotLength = slotLength; + _fileSystem = fileSystem; + _keyStoreConfig = keyStoreConfig; _blockUpToDateCutoff = slotLength; _blockWaitCutoff = _slotLength / 3; @@ -92,11 +103,11 @@ TimeSpan slotLength KeyValidator = new ShutterKeyValidator(_cfg, Eon, logManager); - InitP2P(_cfg, logManager); + InitP2P(ip); } - public Task StartP2P(CancellationTokenSource? cancellationTokenSource = null) - => P2P!.Start(OnKeysReceived, cancellationTokenSource); + public Task StartP2P(Multiaddress[] bootnodeP2PAddresses, CancellationTokenSource? cancellationTokenSource = null) + => P2P!.Start(bootnodeP2PAddresses, OnKeysReceived, cancellationTokenSource); public ShutterBlockImprovementContextFactory GetBlockImprovementContextFactory(IBlockProducer blockProducer) { @@ -138,16 +149,14 @@ protected virtual async Task OnKeysReceived(Dto.DecryptionKeys decryptionKeys) TxSource.LoadTransactions(head, parentHeader, keys.Value); } - protected virtual void InitP2P(IShutterConfig cfg, ILogManager logManager) + protected virtual void InitP2P(IPAddress ip) { - P2P = new ShutterP2P(cfg, logManager); + P2P = new ShutterP2P(_cfg, _logManager, _fileSystem, _keyStoreConfig, ip); } protected virtual IShutterEon InitEon() => new ShutterEon(_readOnlyBlockTree, _txProcessingEnvFactory, _abiEncoder, _cfg, _logManager); protected virtual ShutterTime InitTime(ISpecProvider specProvider, ITimestamper timestamper) - { - return new(specProvider.BeaconChainGenesisTimestamp!.Value * 1000, timestamper, _slotLength, _blockUpToDateCutoff); - } + => new(specProvider.BeaconChainGenesisTimestamp!.Value * 1000, timestamper, _slotLength, _blockUpToDateCutoff); } diff --git a/src/Nethermind/Nethermind.Shutter/ShutterP2P.cs b/src/Nethermind/Nethermind.Shutter/ShutterP2P.cs index 6bd04185038..726df4f29db 100644 --- a/src/Nethermind/Nethermind.Shutter/ShutterP2P.cs +++ b/src/Nethermind/Nethermind.Shutter/ShutterP2P.cs @@ -10,14 +10,15 @@ using System.Threading.Tasks; using System.Threading; using Microsoft.Extensions.DependencyInjection; -using System.Collections.Generic; using Multiformats.Address; using Nethermind.Shutter.Config; using Nethermind.Logging; -using Nethermind.Core.Extensions; using ILogger = Nethermind.Logging.ILogger; using System.Threading.Channels; using Google.Protobuf; +using System.IO.Abstractions; +using Nethermind.KeyStore.Config; +using System.Net; namespace Nethermind.Shutter; @@ -27,6 +28,8 @@ public class ShutterP2P : IShutterP2P private readonly IShutterConfig _cfg; private readonly Channel _msgQueue = Channel.CreateBounded(1000); private readonly PubsubRouter _router; + private readonly PubsubPeerDiscoveryProtocol _disc; + private readonly PeerStore _peerStore; private readonly ILocalPeer _peer; private readonly ServiceProvider _serviceProvider; private CancellationTokenSource? _cts; @@ -35,7 +38,7 @@ public class ShutterP2P : IShutterP2P public class ShutterP2PException(string message, Exception? innerException = null) : Exception(message, innerException); - public ShutterP2P(IShutterConfig shutterConfig, ILogManager logManager) + public ShutterP2P(IShutterConfig shutterConfig, ILogManager logManager, IFileSystem fileSystem, IKeyStoreConfig keyStoreConfig, IPAddress ip) { _logger = logManager.GetClassLogger(); _cfg = shutterConfig; @@ -55,6 +58,9 @@ public ShutterP2P(IShutterConfig shutterConfig, ILogManager logManager) HighestDegree = 6, LazyDegree = 3 }) + .AddSingleton() + .AddSingleton() + .AddSingleton(sp => sp.GetService()!.Build()) //.AddSingleton(new NethermindLoggerFactory(logManager)) // .AddLogging(builder => // builder.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace) @@ -67,9 +73,12 @@ public ShutterP2P(IShutterConfig shutterConfig, ILogManager logManager) .BuildServiceProvider(); IPeerFactory peerFactory = _serviceProvider!.GetService()!; - _peer = peerFactory.Create(new Identity(), "/ip4/0.0.0.0/tcp/" + _cfg.P2PPort); + + Identity identity = GetPeerIdentity(fileSystem, _cfg, keyStoreConfig); + _peer = peerFactory.Create(identity, $"/ip4/{ip}/tcp/{_cfg.P2PPort}"); _router = _serviceProvider!.GetService()!; - ITopic topic = _router.Subscribe("decryptionKeys"); + _disc = new(_router, _peerStore = _serviceProvider.GetService()!, new PubsubPeerDiscoverySettings() { Interval = 300 }, _peer); + ITopic topic = _router.GetTopic("decryptionKeys"); topic.OnMessage += (byte[] msg) => { @@ -78,13 +87,12 @@ public ShutterP2P(IShutterConfig shutterConfig, ILogManager logManager) }; } - public async Task Start(Func onKeysReceived, CancellationTokenSource? cts = null) + public async Task Start(Multiaddress[] bootnodeP2PAddresses, Func onKeysReceived, CancellationTokenSource? cts = null) { - MyProto proto = new(); _cts = cts ?? new(); - _ = _router!.RunAsync(_peer, proto, token: _cts.Token); - proto.SetupFinished().GetAwaiter().GetResult(); - ConnectToPeers(proto, _cfg.BootnodeP2PAddresses!); + _ = _router!.RunAsync(_peer, token: _cts.Token); + _ = _disc.DiscoverAsync(_peer.Address, _cts.Token); + _peerStore.Discover(bootnodeP2PAddresses); if (_logger.IsInfo) _logger.Info($"Started Shutter P2P: {_peer.Address}"); @@ -128,19 +136,26 @@ public async ValueTask DisposeAsync() await (_cts?.CancelAsync() ?? Task.CompletedTask); } - private class MyProto : IDiscoveryProtocol + private Identity GetPeerIdentity(IFileSystem fileSystem, IShutterConfig shutterConfig, IKeyStoreConfig keyStoreConfig) { - private readonly TaskCompletionSource taskCompletionSource = new(); - public Func? OnAddPeer { get; set; } - public Func? OnRemovePeer { get; set; } - - public Task SetupFinished() => taskCompletionSource.Task; + string fp = shutterConfig.ShutterKeyFile.GetApplicationResourcePath(keyStoreConfig.KeyStoreDirectory); + Identity identity; - public Task DiscoverAsync(Multiaddress localPeerAddr, CancellationToken token = default) + if (fileSystem.File.Exists(fp)) { - taskCompletionSource.TrySetResult(); - return Task.CompletedTask; + if (_logger.IsInfo) _logger.Info("Loading Shutter P2P identity from disk."); + identity = new(fileSystem.File.ReadAllBytes(fp)); } + else + { + if (_logger.IsInfo) _logger.Info("Generating new Shutter P2P identity."); + identity = new(); + string keyStoreDirectory = keyStoreConfig.KeyStoreDirectory.GetApplicationResourcePath(); + fileSystem.Directory.CreateDirectory(keyStoreDirectory); + fileSystem.File.WriteAllBytes(fp, identity.PrivateKey!.Data.ToByteArray()); + } + + return identity; } private void ProcessP2PMessage(byte[] msg, Func onKeysReceived) @@ -164,14 +179,4 @@ private void ProcessP2PMessage(byte[] msg, Func onKeys if (_logger.IsDebug) _logger.Warn($"Could not parse Shutter decryption keys: {e}"); } } - - private static void ConnectToPeers(MyProto proto, IEnumerable p2pAddresses) - { - // shuffle peers to connect to random subset of keypers - int seed = (int)(DateTimeOffset.Now.ToUnixTimeSeconds() % int.MaxValue); - foreach (string addr in p2pAddresses.Shuffle(new Random(seed))) - { - proto.OnAddPeer?.Invoke([addr]); - } - } } diff --git a/src/Nethermind/Nethermind.Shutter/ShutterPlugin.cs b/src/Nethermind/Nethermind.Shutter/ShutterPlugin.cs index 04b6a444699..bc75443016c 100644 --- a/src/Nethermind/Nethermind.Shutter/ShutterPlugin.cs +++ b/src/Nethermind/Nethermind.Shutter/ShutterPlugin.cs @@ -16,6 +16,8 @@ using Nethermind.Serialization.Json; using System.Threading; using Nethermind.Config; +using Multiformats.Address; +using Nethermind.KeyStore.Config; namespace Nethermind.Shutter; @@ -70,12 +72,14 @@ public IBlockProducer InitBlockProducer(IBlockProducerFactory consensusPlugin, I if (_api.SpecProvider is null) throw new ArgumentNullException(nameof(_api.SpecProvider)); if (_api.ReceiptFinder is null) throw new ArgumentNullException(nameof(_api.ReceiptFinder)); if (_api.WorldStateManager is null) throw new ArgumentNullException(nameof(_api.WorldStateManager)); + if (_api.IpResolver is null) throw new ArgumentNullException(nameof(_api.IpResolver)); if (_logger.IsInfo) _logger.Info("Initializing Shutter block producer."); + Multiaddress[] bootnodeP2PAddresses; try { - _shutterConfig!.Validate(); + _shutterConfig!.Validate(out bootnodeP2PAddresses); } catch (ArgumentException e) { @@ -105,12 +109,15 @@ public IBlockProducer InitBlockProducer(IBlockProducerFactory consensusPlugin, I _api.SpecProvider, _api.Timestamper, _api.WorldStateManager, + _api.FileSystem, + _api.Config(), _shutterConfig, validatorsInfo, - TimeSpan.FromSeconds(_blocksConfig!.SecondsPerSlot) + TimeSpan.FromSeconds(_blocksConfig!.SecondsPerSlot), + _api.IpResolver.ExternalIp ); - _ = _shutterApi.StartP2P(_cts); + _ = _shutterApi.StartP2P(bootnodeP2PAddresses, _cts); } return consensusPlugin.InitBlockProducer(_shutterApi is null ? txSource : _shutterApi.TxSource.Then(txSource));