From a41568e638b161a01d751dc784e285391acae7db Mon Sep 17 00:00:00 2001 From: TheDude Date: Wed, 29 Sep 2021 13:42:38 +0100 Subject: [PATCH 01/13] Moved output to dedicated classes --- src/Lyn.Protocol/Bolt1/InitMessageService.cs | 14 ++-------- src/Lyn.Protocol/Bolt1/PingMessageService.cs | 6 +---- .../AcceptChannelMessageService.cs | 16 +++++------ .../FundingCreatedMessageService.cs | 2 +- .../FundingSignedMessageService.cs | 8 +++--- .../OpenChannelMessageService.cs | 13 +++++---- .../Messages/ErrorCloseChannelResponse.cs | 27 +++++++++++++++++++ .../Messages/MessageProcessingOutput.cs | 19 ------------- .../Messages/SuccessWithOutputResponse.cs | 12 +++++++++ 9 files changed, 61 insertions(+), 56 deletions(-) create mode 100644 src/Lyn.Protocol/Common/Messages/ErrorCloseChannelResponse.cs create mode 100644 src/Lyn.Protocol/Common/Messages/SuccessWithOutputResponse.cs diff --git a/src/Lyn.Protocol/Bolt1/InitMessageService.cs b/src/Lyn.Protocol/Bolt1/InitMessageService.cs index fd75b5b..b6fc9e1 100644 --- a/src/Lyn.Protocol/Bolt1/InitMessageService.cs +++ b/src/Lyn.Protocol/Bolt1/InitMessageService.cs @@ -50,13 +50,7 @@ public async Task ProcessMessageAsync(PeerMessage GenerateInitAsync(PublicKey nodeId, CancellationToken token) { - var response = new MessageProcessingOutput - { - Success = true, - ResponseMessages = new[] {CreateInitMessage()} - }; + var response = new SuccessWithOutputResponse(CreateInitMessage()); if (_repository.PeerExists(nodeId)) return response; diff --git a/src/Lyn.Protocol/Bolt1/PingMessageService.cs b/src/Lyn.Protocol/Bolt1/PingMessageService.cs index 24dd25a..e755d4c 100644 --- a/src/Lyn.Protocol/Bolt1/PingMessageService.cs +++ b/src/Lyn.Protocol/Bolt1/PingMessageService.cs @@ -54,11 +54,7 @@ public async Task ProcessMessageAsync(PeerMessage ProcessMessageAsync(PeerMessage ProcessMessageAsync(PeerMessage chainParameters.ChannelBoundariesConfig.MinimumDepth) { - return MessageProcessingOutput.CreateErrorMessage(acceptChannel.TemporaryChannelId, true, "minimum_depth is unreasonably large"); + return new ErrorCloseChannelResponse(acceptChannel.TemporaryChannelId, "minimum_depth is unreasonably large"); } if (acceptChannel.DustLimitSatoshis > channelCandidate.OpenChannel.ChannelReserveSatoshis) { - return MessageProcessingOutput.CreateErrorMessage(acceptChannel.TemporaryChannelId, true, "channel_reserve_satoshis is less than dust_limit_satoshis within the open_channel message"); + return new ErrorCloseChannelResponse(acceptChannel.TemporaryChannelId, "channel_reserve_satoshis is less than dust_limit_satoshis within the open_channel message"); } if (channelCandidate.OpenChannel.DustLimitSatoshis > acceptChannel.ChannelReserveSatoshis) { - return MessageProcessingOutput.CreateErrorMessage(acceptChannel.TemporaryChannelId, true, "channel_reserve_satoshis from the open_channel message is less than dust_limit_satoshis"); + return new ErrorCloseChannelResponse(acceptChannel.TemporaryChannelId, "channel_reserve_satoshis from the open_channel message is less than dust_limit_satoshis"); } channelCandidate.AcceptChannel = acceptChannel; @@ -191,7 +191,7 @@ public async Task ProcessMessageAsync(PeerMessage ProcessMessageAsync(PeerMessage ProcessMessageAsync(PeerMessage ProcessMessageAsync(PeerMessage ProcessMessageAsync(PeerMessage ProcessMessageAsync(PeerMessage ProcessMessageAsync(PeerMessage ProcessMessageAsync(PeerMessage ProcessMessageAsync(PeerMessage ProcessMessageAsync(PeerMessage Date: Wed, 29 Sep 2021 14:15:42 +0100 Subject: [PATCH 02/13] Minor refactoring of features code --- .../Bolt1/InitMessageServiceTests.cs | 8 ++++---- .../FullChannelEstablishmentTest.cs | 2 +- .../Bolt2/OpenChannelMessageServiceTests.cs | 2 +- .../Bolt2/StartOpenChannelServiceTests.cs | 2 +- src/Lyn.Protocol/Bolt1/Entities/Peer.cs | 9 ++++++++- src/Lyn.Protocol/Bolt1/IPeerRepository.cs | 2 +- src/Lyn.Protocol/Bolt1/InMemoryPeerRepository.cs | 6 ++++-- src/Lyn.Protocol/Bolt1/InitMessageService.cs | 9 ++++----- .../AcceptChannelMessageService.cs | 8 ++++---- .../FundingSignedMessageService.cs | 8 ++++---- .../OpenChannelMessageService.cs | 8 ++++---- .../ChannelEstablishment/StartOpenChannelService.cs | 12 ++++++------ src/Lyn.Protocol/Bolt9/IBoltFeatures.cs | 2 ++ src/Lyn.Protocol/Bolt9/LynImplementedBoltFeatures.cs | 5 +++++ 14 files changed, 49 insertions(+), 34 deletions(-) diff --git a/src/Lyn.Protocol.Tests/Bolt1/InitMessageServiceTests.cs b/src/Lyn.Protocol.Tests/Bolt1/InitMessageServiceTests.cs index f62777c..30d774b 100644 --- a/src/Lyn.Protocol.Tests/Bolt1/InitMessageServiceTests.cs +++ b/src/Lyn.Protocol.Tests/Bolt1/InitMessageServiceTests.cs @@ -127,7 +127,7 @@ public void ProcessMessageAddsPeerAndSendsResponse() _sut.ProcessMessageAsync(message); _repository.Verify(_ => _.AddOrUpdatePeerAsync(It.Is(p - => (ulong)p.Featurs == (ulong)parsedFeatures && + => (ulong)p.Features == (ulong)parsedFeatures && p.NodeId.Equals(message.NodeId)))); } @@ -158,17 +158,17 @@ public void ProcessMessageUpdatesPeerAndSendsResponse() var peer = new Peer { NodeId = message.NodeId, - Featurs = (Features) RandomMessages.GetRandomNumberUInt16() + Features = (Features) RandomMessages.GetRandomNumberUInt16() }; _repository.Setup(_ => _.TryGetPeerAsync(message.NodeId)) - .Returns(peer); + .Returns(Task.FromResult(peer)); _sut.ProcessMessageAsync(message); _repository.Verify(_ => _.AddOrUpdatePeerAsync(peer)); - Assert.Equal(peer.Featurs,parsedFeatures); + Assert.Equal(peer.Features,parsedFeatures); } [Fact] diff --git a/src/Lyn.Protocol.Tests/Bolt2/ChannelEstablishment/FullChannelEstablishmentTest.cs b/src/Lyn.Protocol.Tests/Bolt2/ChannelEstablishment/FullChannelEstablishmentTest.cs index 0fafa66..7568eab 100644 --- a/src/Lyn.Protocol.Tests/Bolt2/ChannelEstablishment/FullChannelEstablishmentTest.cs +++ b/src/Lyn.Protocol.Tests/Bolt2/ChannelEstablishment/FullChannelEstablishmentTest.cs @@ -106,7 +106,7 @@ public FullChannelEstablishmentTest() _peerRepository.AddNewPeerAsync(new Peer { - Featurs = Features.InitialRoutingSync | Features.VarOnionOptin | Features.GossipQueriesEx | + Features = Features.InitialRoutingSync | Features.VarOnionOptin | Features.GossipQueriesEx | Features.PaymentSecret | (Features)2, Id = 0, GlobalFeatures = Features.OptionDataLossProtect, diff --git a/src/Lyn.Protocol.Tests/Bolt2/OpenChannelMessageServiceTests.cs b/src/Lyn.Protocol.Tests/Bolt2/OpenChannelMessageServiceTests.cs index c06b594..3d242ff 100644 --- a/src/Lyn.Protocol.Tests/Bolt2/OpenChannelMessageServiceTests.cs +++ b/src/Lyn.Protocol.Tests/Bolt2/OpenChannelMessageServiceTests.cs @@ -76,7 +76,7 @@ private ChainParameters WithExistingPeerAndChainParameters(PeerMessage _.TryGetPeerAsync(message.NodeId)).Returns(new Peer()); + _peerRepository.Setup(_ => _.TryGetPeerAsync(message.NodeId)).Returns(Task.FromResult(new Peer())); _chainConfigProvider.Setup(_ => _.GetConfiguration(message.MessagePayload.ChainHash)).Returns(chainParameters); _lightningTransactions.Setup(_ => _.GetBaseFee(It.IsAny(), It.IsAny(), 0)).Returns(100); diff --git a/src/Lyn.Protocol.Tests/Bolt2/StartOpenChannelServiceTests.cs b/src/Lyn.Protocol.Tests/Bolt2/StartOpenChannelServiceTests.cs index a79e6c0..28cb91b 100644 --- a/src/Lyn.Protocol.Tests/Bolt2/StartOpenChannelServiceTests.cs +++ b/src/Lyn.Protocol.Tests/Bolt2/StartOpenChannelServiceTests.cs @@ -70,7 +70,7 @@ private ChainParameters WithExistingPeerAndChainParameters(CreateOpenChannelIn m }, }; - _peerRepository.Setup(_ => _.TryGetPeerAsync(message.NodeId)).Returns(new Peer()); + _peerRepository.Setup(_ => _.TryGetPeerAsync(message.NodeId)).Returns(Task.FromResult(new Peer())); _chainConfigProvider.Setup(_ => _.GetConfiguration(message.ChainHash)).Returns(chainParameters); return chainParameters; diff --git a/src/Lyn.Protocol/Bolt1/Entities/Peer.cs b/src/Lyn.Protocol/Bolt1/Entities/Peer.cs index f66f833..1f2ec1d 100644 --- a/src/Lyn.Protocol/Bolt1/Entities/Peer.cs +++ b/src/Lyn.Protocol/Bolt1/Entities/Peer.cs @@ -9,8 +9,15 @@ public class Peer public PublicKey NodeId { get; set; } - public Features Featurs { get; set; } + public Features Features { get; set; } public Features GlobalFeatures { get; set; } + + public Features MutuallySupportedFeatures { get; set; } + + public bool SupportsFeature(Features feature) + { + return (Features & Features.OptionUpfrontShutdownScript) != 0; + } } } \ No newline at end of file diff --git a/src/Lyn.Protocol/Bolt1/IPeerRepository.cs b/src/Lyn.Protocol/Bolt1/IPeerRepository.cs index 47dfa72..3961c7b 100644 --- a/src/Lyn.Protocol/Bolt1/IPeerRepository.cs +++ b/src/Lyn.Protocol/Bolt1/IPeerRepository.cs @@ -10,7 +10,7 @@ public interface IPeerRepository Task AddNewPeerAsync(Peer peer); Task AddErrorMessageToPeerAsync(PublicKey nodeId, PeerCommunicationIssue errorMessage); bool PeerExists(PublicKey nodeId); - Peer? TryGetPeerAsync(PublicKey nodeId); + Task TryGetPeerAsync(PublicKey nodeId); Task AddOrUpdatePeerAsync(Peer peer); } } \ No newline at end of file diff --git a/src/Lyn.Protocol/Bolt1/InMemoryPeerRepository.cs b/src/Lyn.Protocol/Bolt1/InMemoryPeerRepository.cs index 52c92f3..07d1fa5 100644 --- a/src/Lyn.Protocol/Bolt1/InMemoryPeerRepository.cs +++ b/src/Lyn.Protocol/Bolt1/InMemoryPeerRepository.cs @@ -40,11 +40,13 @@ public bool PeerExists(PublicKey nodeId) return Peers.ContainsKey(nodeId); } - public Peer? TryGetPeerAsync(PublicKey nodeId) + public Task TryGetPeerAsync(PublicKey nodeId) { var key = Peers.Keys.FirstOrDefault(_ => _.Equals(nodeId)); - return key != null ? Peers[key] : null; //Hack for quick debug + return key != null + ? Task.FromResult(Peers[key]) + : Task.FromResult(null); } public Task AddOrUpdatePeerAsync(Peer peer) diff --git a/src/Lyn.Protocol/Bolt1/InitMessageService.cs b/src/Lyn.Protocol/Bolt1/InitMessageService.cs index b6fc9e1..c3acb77 100644 --- a/src/Lyn.Protocol/Bolt1/InitMessageService.cs +++ b/src/Lyn.Protocol/Bolt1/InitMessageService.cs @@ -37,15 +37,14 @@ public async Task ProcessMessageAsync(PeerMessage ProcessMessageAsync(PeerMessage ProcessMessageAsync(PeerMessage ProcessMessageAsync(PeerMessage ProcessMessageAsync(PeerMessage ProcessMessageAsync(PeerMessage ProcessMessageAsync(PeerMessage ProcessMessageAsync(PeerMessage ProcessMessageAsync(PeerMessage logger, public async Task CreateOpenChannelAsync(CreateOpenChannelIn createOpenChannelIn) { - var peer = _peerRepository.TryGetPeerAsync(createOpenChannelIn.NodeId); + var peer = await _peerRepository.TryGetPeerAsync(createOpenChannelIn.NodeId); if (peer == null) throw new ApplicationException($"Peer was not found or is not connected"); @@ -73,8 +73,8 @@ public async Task CreateOpenChannelAsync(CreateOpenChannelIn create if (createOpenChannelIn.PrivateChannel && !chainParameters.ChannelBoundariesConfig.AllowPrivateChannels) throw new ApplicationException($"Private channels are not enabled"); - bool localSupportLargeChannels = (_boltFeatures.SupportedFeatures & Features.OptionSupportLargeChannel) != 0; - bool remoteSupportLargeChannels = (peer.Featurs & Features.OptionSupportLargeChannel) != 0; + var localSupportLargeChannels = _boltFeatures.SupportsFeature(Features.OptionSupportLargeChannel); + var remoteSupportLargeChannels = peer.SupportsFeature(Features.OptionSupportLargeChannel); if (localSupportLargeChannels == false || remoteSupportLargeChannels == false) { @@ -117,9 +117,9 @@ public async Task CreateOpenChannelAsync(CreateOpenChannelIn create openChannel.MaxHtlcValueInFlightMsat = chainParameters.ChannelConfig.MaxHtlcValueInFlight; openChannel.MaxAcceptedHtlcs = chainParameters.ChannelConfig.MaxAcceptedHtlcs; - byte[]? upfrontShutdownScript = chainParameters.ChannelConfig.UpfrontShutdownScript; - bool localSupportUpfrontShutdownScript = (_boltFeatures.SupportedFeatures & Features.OptionUpfrontShutdownScript) != 0; - bool remoteSupportUpfrontShutdownScript = (peer.Featurs & Features.OptionUpfrontShutdownScript) != 0; + var upfrontShutdownScript = chainParameters.ChannelConfig.UpfrontShutdownScript; + var localSupportUpfrontShutdownScript = _boltFeatures.SupportsFeature(Features.OptionUpfrontShutdownScript); + var remoteSupportUpfrontShutdownScript = peer.SupportsFeature(Features.OptionUpfrontShutdownScript); if (localSupportUpfrontShutdownScript && remoteSupportUpfrontShutdownScript) { diff --git a/src/Lyn.Protocol/Bolt9/IBoltFeatures.cs b/src/Lyn.Protocol/Bolt9/IBoltFeatures.cs index f2a5e20..8c9ceed 100644 --- a/src/Lyn.Protocol/Bolt9/IBoltFeatures.cs +++ b/src/Lyn.Protocol/Bolt9/IBoltFeatures.cs @@ -6,6 +6,8 @@ public interface IBoltFeatures { Features SupportedFeatures { get; } + bool SupportsFeature(Features feature); + byte[] GetSupportedFeatures(); byte[] GetSupportedGlobalFeatures(); diff --git a/src/Lyn.Protocol/Bolt9/LynImplementedBoltFeatures.cs b/src/Lyn.Protocol/Bolt9/LynImplementedBoltFeatures.cs index 2e0a5d7..31547a6 100644 --- a/src/Lyn.Protocol/Bolt9/LynImplementedBoltFeatures.cs +++ b/src/Lyn.Protocol/Bolt9/LynImplementedBoltFeatures.cs @@ -19,6 +19,11 @@ public LynImplementedBoltFeatures(IParseFeatureFlags parseFeatureFlags) _globalBytes = parseFeatureFlags.ParseNFeatures(FEATURES, 13); } + public bool SupportsFeature(Features feature) + { + return (SupportedFeatures & feature) != 0; + } + public byte[] GetSupportedFeatures() => _bytes; public byte[] GetSupportedGlobalFeatures() => _globalBytes; From bac06bd9a80eb000c6f0b84d05120dff6b22da4c Mon Sep 17 00:00:00 2001 From: TheDude Date: Thu, 14 Oct 2021 12:54:05 +0100 Subject: [PATCH 03/13] From CRLF to LF --- docker/test-network/c-lightning/Dockerfile | 2 +- docker/test-network/c-lightning/lightningd/config | 4 +--- docker/test-network/docker-compose.yml | 3 ++- docker/test-network/lnd/lnd/lnd.conf | 1 - 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/docker/test-network/c-lightning/Dockerfile b/docker/test-network/c-lightning/Dockerfile index 132e939..2b36c6a 100644 --- a/docker/test-network/c-lightning/Dockerfile +++ b/docker/test-network/c-lightning/Dockerfile @@ -28,7 +28,7 @@ RUN chmod +x /usr/local/bin/logtail.sh ADD wait-for-bitcoind.sh /usr/local/bin RUN chmod +x /usr/local/bin/wait-for-bitcoind.sh -RUN curl -sL https://deb.nodesource.com/setup_10.x | bash - \ +RUN curl -sL https://deb.nodesource.com/setup_14.x | bash - \ && apt-get install -y nodejs \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* diff --git a/docker/test-network/c-lightning/lightningd/config b/docker/test-network/c-lightning/lightningd/config index 641388e..414e376 100644 --- a/docker/test-network/c-lightning/lightningd/config +++ b/docker/test-network/c-lightning/lightningd/config @@ -9,6 +9,4 @@ bitcoin-rpcport=18443 log-level=debug log-file=/lightningd/lightningd.log -plugin=/rest/plugin.js -rest-port=3002 -rest-docport=4001 \ No newline at end of file +plugin=/rest/plugin.js \ No newline at end of file diff --git a/docker/test-network/docker-compose.yml b/docker/test-network/docker-compose.yml index e0e2823..89dc52d 100644 --- a/docker/test-network/docker-compose.yml +++ b/docker/test-network/docker-compose.yml @@ -17,6 +17,8 @@ services: - "18443" - "12005" - "12006" + ports: + - "0.0.0.0:18443:18443" restart: always lnd-node: @@ -34,7 +36,6 @@ services: c-lightning-node: container_name: c-lightning-node - hostname: c-lightning-node hostname: lightning build: context: c-lightning diff --git a/docker/test-network/lnd/lnd/lnd.conf b/docker/test-network/lnd/lnd/lnd.conf index af90cdc..e161217 100644 --- a/docker/test-network/lnd/lnd/lnd.conf +++ b/docker/test-network/lnd/lnd/lnd.conf @@ -5,7 +5,6 @@ listen=0.0.0.0 nobootstrap=1 noseedbackup=1 debuglevel=info -port=9732 [bitcoin] bitcoin.active=1 From 249ae2a5af4bbd42d79b7b5a2510b9608122eed1 Mon Sep 17 00:00:00 2001 From: TheDude Date: Tue, 19 Oct 2021 14:57:20 +0100 Subject: [PATCH 04/13] Received funding locked --- .../Bolt2/AcceptChannelMessageServiceTests.cs | 5 +- .../FullChannelEstablishmentTest.cs | 22 +++-- .../Bolt2/StartOpenChannelServiceTests.cs | 17 +++- .../Bolt3/Bolt3CommitmentTestContext.cs | 4 +- src/Lyn.Protocol/Bolt1/Messages/Features.cs | 3 +- .../AcceptChannelMessageService.cs | 30 ++++--- .../FundingSignedMessageService.cs | 39 ++++----- .../StartOpenChannelService.cs | 28 ++++--- .../Bolt2/Wallet/IWalletTransactions.cs | 15 ++++ .../Bolt2/Wallet/WalletTransactions.cs | 80 +++++++++++++++++++ .../Bolt3/LightningKeyDerivation.cs | 6 +- .../Bolt9/LynImplementedBoltFeatures.cs | 2 +- .../Common/DefaultIoCRegistrations.cs | 3 + .../ITransactionHashCalculator.cs | 2 +- .../TransactionHashCalculator.cs | 6 +- src/Lyn.Types/Hex.cs | 8 +- 16 files changed, 195 insertions(+), 75 deletions(-) create mode 100644 src/Lyn.Protocol/Bolt2/Wallet/IWalletTransactions.cs create mode 100644 src/Lyn.Protocol/Bolt2/Wallet/WalletTransactions.cs rename src/Lyn.Protocol/Common/{ => Hashing}/ITransactionHashCalculator.cs (84%) rename src/Lyn.Protocol/Common/{ => Hashing}/TransactionHashCalculator.cs (92%) diff --git a/src/Lyn.Protocol.Tests/Bolt2/AcceptChannelMessageServiceTests.cs b/src/Lyn.Protocol.Tests/Bolt2/AcceptChannelMessageServiceTests.cs index 994ca78..c8c1e35 100644 --- a/src/Lyn.Protocol.Tests/Bolt2/AcceptChannelMessageServiceTests.cs +++ b/src/Lyn.Protocol.Tests/Bolt2/AcceptChannelMessageServiceTests.cs @@ -4,10 +4,12 @@ using Lyn.Protocol.Bolt1.Entities; using Lyn.Protocol.Bolt2.ChannelEstablishment; using Lyn.Protocol.Bolt2.ChannelEstablishment.Messages; +using Lyn.Protocol.Bolt2.Wallet; using Lyn.Protocol.Bolt3; using Lyn.Protocol.Bolt9; using Lyn.Protocol.Common; using Lyn.Protocol.Common.Blockchain; +using Lyn.Protocol.Common.Hashing; using Lyn.Protocol.Common.Messages; using Lyn.Protocol.Connection; using Lyn.Types; @@ -54,7 +56,8 @@ public AcceptChannelMessageServiceTests() new ChainConfigProvider(), _store.Object, inMemoryPeerRepository, - _features.Object); + _features.Object, + new Mock().Object); } } } \ No newline at end of file diff --git a/src/Lyn.Protocol.Tests/Bolt2/ChannelEstablishment/FullChannelEstablishmentTest.cs b/src/Lyn.Protocol.Tests/Bolt2/ChannelEstablishment/FullChannelEstablishmentTest.cs index 7568eab..2a8df4a 100644 --- a/src/Lyn.Protocol.Tests/Bolt2/ChannelEstablishment/FullChannelEstablishmentTest.cs +++ b/src/Lyn.Protocol.Tests/Bolt2/ChannelEstablishment/FullChannelEstablishmentTest.cs @@ -6,10 +6,12 @@ using Lyn.Protocol.Bolt1.Messages; using Lyn.Protocol.Bolt2.ChannelEstablishment; using Lyn.Protocol.Bolt2.ChannelEstablishment.Messages; +using Lyn.Protocol.Bolt2.Wallet; using Lyn.Protocol.Bolt3; using Lyn.Protocol.Bolt9; using Lyn.Protocol.Common; using Lyn.Protocol.Common.Blockchain; +using Lyn.Protocol.Common.Hashing; using Lyn.Protocol.Common.Messages; using Lyn.Protocol.Connection; using Lyn.Types; @@ -70,15 +72,20 @@ public FullChannelEstablishmentTest() new TransactionOutputSerializer(), new TransactionWitnessSerializer(new TransactionWitnessComponentSerializer()))); - _openChannelService = new StartOpenChannelService(new Logger(loggerFactory), + var walletLookup = new Mock(); + + walletLookup.Setup(_ => _.IsAmountAvailableAsync(It.IsAny())) + .ReturnsAsync(true); + + _openChannelService = new StartOpenChannelService(new Logger(loggerFactory), _randomNumberGenerator.Object, _keyDerivation, _candidateRepository, _peerRepository, new ChainConfigProvider(), new LynImplementedBoltFeatures(parsingFeatures), - parsingFeatures, - new SecretStore()); + new SecretStore(), + walletLookup.Object); _acceptChannelMessageService = new AcceptChannelMessageService( new Logger(loggerFactory), @@ -89,19 +96,20 @@ public FullChannelEstablishmentTest() _candidateRepository, new ChainConfigProvider(), new SecretStore(), - _peerRepository, new LynImplementedBoltFeatures(parsingFeatures)); + _peerRepository, + new LynImplementedBoltFeatures(parsingFeatures), + walletLookup.Object); _fundingSignedMessageService = new FundingSignedMessageService( new Logger(loggerFactory), lightningTransactions, - hashCalculator, _lightningScripts, _keyDerivation, _candidateRepository, new ChainConfigProvider(), - new SecretStore(), _peerRepository, - new LynImplementedBoltFeatures(parsingFeatures)); + new LynImplementedBoltFeatures(parsingFeatures), + walletLookup.Object); _peerRepository.AddNewPeerAsync(new Peer diff --git a/src/Lyn.Protocol.Tests/Bolt2/StartOpenChannelServiceTests.cs b/src/Lyn.Protocol.Tests/Bolt2/StartOpenChannelServiceTests.cs index 28cb91b..7efdb40 100644 --- a/src/Lyn.Protocol.Tests/Bolt2/StartOpenChannelServiceTests.cs +++ b/src/Lyn.Protocol.Tests/Bolt2/StartOpenChannelServiceTests.cs @@ -15,6 +15,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Lyn.Protocol.Bolt2.Wallet; using Xunit; namespace Lyn.Protocol.Tests.Bolt2 @@ -25,13 +26,13 @@ public class StartOpenChannelServiceTests private readonly Mock _peerRepository = new(); private readonly Mock _features = new(); - private readonly Mock> _logger = new(); + private readonly Mock> _logger = new(); private readonly Mock _randomNumberGenerator = new(); private readonly LightningKeyDerivation _lightningKeyDerivation = new(); private readonly Mock _channelStateRepository = new(); private readonly Mock _chainConfigProvider = new(); - private readonly Mock _parseFeatureFlags = new(); private readonly Mock _secretProvider = new(); + private readonly Mock _transactionsLookups = new(); private readonly Secret _randomSecret; @@ -40,8 +41,8 @@ public StartOpenChannelServiceTests() _sut = new StartOpenChannelService(_logger.Object, _randomNumberGenerator.Object, _lightningKeyDerivation, _channelStateRepository.Object, _peerRepository.Object, - _chainConfigProvider.Object, _features.Object, - _parseFeatureFlags.Object, _secretProvider.Object); + _chainConfigProvider.Object, _features.Object, _secretProvider.Object, + _transactionsLookups.Object); _randomSecret = new Secret(RandomMessages.GetRandomByteArray(32)); @@ -95,9 +96,17 @@ private CreateOpenChannelIn NewStartChannelMessage() return (fundingPubkey, basepoints); } + private void WithEnoughFundsInTheWallet() + { + _transactionsLookups.Setup(_ => _.IsAmountAvailableAsync(It.IsAny())) + .Returns(Task.FromResult(true)); + } + [Fact] public async Task StartOpenChannelSuccess() { + WithEnoughFundsInTheWallet(); + var message = NewStartChannelMessage(); var config = WithExistingPeerAndChainParameters(message); diff --git a/src/Lyn.Protocol.Tests/Bolt3/Bolt3CommitmentTestContext.cs b/src/Lyn.Protocol.Tests/Bolt3/Bolt3CommitmentTestContext.cs index c3be5a3..9443320 100644 --- a/src/Lyn.Protocol.Tests/Bolt3/Bolt3CommitmentTestContext.cs +++ b/src/Lyn.Protocol.Tests/Bolt3/Bolt3CommitmentTestContext.cs @@ -1,9 +1,11 @@ using System; using System.Buffers; using System.Linq; +using FluentAssertions; using Lyn.Protocol.Bolt3; using Lyn.Protocol.Bolt3.Types; using Lyn.Protocol.Common; +using Lyn.Protocol.Common.Hashing; using Lyn.Protocol.Common.Messages; using Lyn.Types; using Lyn.Types.Bitcoin; @@ -135,7 +137,7 @@ public Bolt3CommitmentTestContext() // dotnet has no uint48 types so we use ulong instead, however ulong (which is uint64) has two // more bytes in the array then just drop the last to bytes form the array to compute the hex - Assert.Equal("0x2bb038521914", Hex.ToString(BitConverter.GetBytes(CnObscurer).Reverse().ToArray().AsSpan().Slice(2))); + Assert.Equal("0x2bb038521914", $"0x{Hex.ToString(BitConverter.GetBytes(CnObscurer).Reverse().ToArray().AsSpan().Slice(2))}"); Keyset = new Keyset(RemoteRevocationKey, LocalHtlckey, RemoteHtlckey, LocalDelayedkey, Remotekey); } diff --git a/src/Lyn.Protocol/Bolt1/Messages/Features.cs b/src/Lyn.Protocol/Bolt1/Messages/Features.cs index 3081a4c..1db20ae 100644 --- a/src/Lyn.Protocol/Bolt1/Messages/Features.cs +++ b/src/Lyn.Protocol/Bolt1/Messages/Features.cs @@ -5,8 +5,9 @@ namespace Lyn.Protocol.Bolt1.Messages [Flags] public enum Features : ulong { - OptionDataLossProtect = 0, OptionDataLossProtectRequired = 1 << 0, + OptionDataLossProtect = 1 << 1, + NotSupported = 1 << 2, InitialRoutingSync = 1 << 3, OptionUpfrontShutdownScriptRequired = 1 << 4, OptionUpfrontShutdownScript = 1 << 5, diff --git a/src/Lyn.Protocol/Bolt2/ChannelEstablishment/AcceptChannelMessageService.cs b/src/Lyn.Protocol/Bolt2/ChannelEstablishment/AcceptChannelMessageService.cs index 65aa225..d16a5d7 100644 --- a/src/Lyn.Protocol/Bolt2/ChannelEstablishment/AcceptChannelMessageService.cs +++ b/src/Lyn.Protocol/Bolt2/ChannelEstablishment/AcceptChannelMessageService.cs @@ -1,6 +1,7 @@ using System; using System.Buffers; using System.Collections.Generic; +using System.Linq; using Lyn.Protocol.Bolt2.ChannelEstablishment.Entities; using Lyn.Protocol.Bolt2.ChannelEstablishment.Messages; using Lyn.Protocol.Bolt3; @@ -14,7 +15,9 @@ using System.Threading.Tasks; using Lyn.Protocol.Bolt1; using Lyn.Protocol.Bolt1.Messages; +using Lyn.Protocol.Bolt2.Wallet; using Lyn.Protocol.Bolt9; +using Lyn.Protocol.Common.Hashing; using Lyn.Types; using Lyn.Types.Fundamental; using Microsoft.Extensions.DependencyInjection; @@ -33,6 +36,7 @@ public class AcceptChannelMessageService : IBoltMessageService private readonly ISecretStore _secretStore; private readonly IPeerRepository _peerRepository; private readonly IBoltFeatures _boltFeatures; + private readonly IWalletTransactions _walletTransactions; public AcceptChannelMessageService(ILogger logger, ILightningTransactions lightningTransactions, @@ -43,7 +47,8 @@ public AcceptChannelMessageService(ILogger logger, IChainConfigProvider chainConfigProvider, ISecretStore secretStore, IPeerRepository peerRepository, - IBoltFeatures boltFeatures) + IBoltFeatures boltFeatures, + IWalletTransactions walletTransactions) { _logger = logger; _lightningTransactions = lightningTransactions; @@ -55,6 +60,7 @@ public AcceptChannelMessageService(ILogger logger, _secretStore = secretStore; _peerRepository = peerRepository; _boltFeatures = boltFeatures; + _walletTransactions = walletTransactions; } public async Task ProcessMessageAsync(PeerMessage message) @@ -114,22 +120,14 @@ public async Task ProcessMessageAsync(PeerMessage { private readonly ILogger _logger; private readonly ILightningTransactions _lightningTransactions; - private readonly ITransactionHashCalculator _transactionHashCalculator; private readonly ILightningScripts _lightningScripts; private readonly ILightningKeyDerivation _lightningKeyDerivation; private readonly IChannelCandidateRepository _channelCandidateRepository; private readonly IChainConfigProvider _chainConfigProvider; - private readonly ISecretStore _secretStore; private readonly IPeerRepository _peerRepository; private readonly IBoltFeatures _boltFeatures; + private readonly IWalletTransactions _walletTransactions; public FundingSignedMessageService(ILogger logger, ILightningTransactions lightningTransactions, - ITransactionHashCalculator transactionHashCalculator, ILightningScripts lightningScripts, ILightningKeyDerivation lightningKeyDerivation, IChannelCandidateRepository channelCandidateRepository, IChainConfigProvider chainConfigProvider, - ISecretStore secretStore, IPeerRepository peerRepository, - IBoltFeatures boltFeatures) + IBoltFeatures boltFeatures, + IWalletTransactions walletTransactions) { _logger = logger; _lightningTransactions = lightningTransactions; - _transactionHashCalculator = transactionHashCalculator; _lightningScripts = lightningScripts; _lightningKeyDerivation = lightningKeyDerivation; _channelCandidateRepository = channelCandidateRepository; _chainConfigProvider = chainConfigProvider; - _secretStore = secretStore; _peerRepository = peerRepository; _boltFeatures = boltFeatures; + _walletTransactions = walletTransactions; } public async Task ProcessMessageAsync(PeerMessage message) @@ -106,21 +104,24 @@ public async Task ProcessMessageAsync(PeerMessage _logger; + private readonly ILogger _logger; private readonly IRandomNumberGenerator _randomNumberGenerator; private readonly ILightningKeyDerivation _lightningKeyDerivation; private readonly IChannelCandidateRepository _channelStateRepository; private readonly IPeerRepository _peerRepository; private readonly IChainConfigProvider _chainConfigProvider; private readonly IBoltFeatures _boltFeatures; - private readonly IParseFeatureFlags _parseFeatureFlags; private readonly ISecretStore _secretStore; + private readonly IWalletTransactions _transactionsLookups; - public StartOpenChannelService(ILogger logger, + public StartOpenChannelService(ILogger logger, IRandomNumberGenerator randomNumberGenerator, ILightningKeyDerivation lightningKeyDerivation, IChannelCandidateRepository channelStateRepository, IPeerRepository peerRepository, IChainConfigProvider chainConfigProvider, IBoltFeatures boltFeatures, - IParseFeatureFlags parseFeatureFlags, - ISecretStore secretStore) + ISecretStore secretStore, IWalletTransactions transactionsLookups) { _logger = logger; _randomNumberGenerator = randomNumberGenerator; @@ -48,8 +47,8 @@ public StartOpenChannelService(ILogger logger, _peerRepository = peerRepository; _chainConfigProvider = chainConfigProvider; _boltFeatures = boltFeatures; - _parseFeatureFlags = parseFeatureFlags; _secretStore = secretStore; + _transactionsLookups = transactionsLookups; } public async Task CreateOpenChannelAsync(CreateOpenChannelIn createOpenChannelIn) @@ -64,12 +63,15 @@ public async Task CreateOpenChannelAsync(CreateOpenChannelIn create if (chainParameters == null) throw new ApplicationException($"Invalid chain hash"); - OpenChannel openChannel = new(); - - openChannel.ChainHash = chainParameters.Chainhash; - - openChannel.TemporaryChannelId = new UInt256(_randomNumberGenerator.GetBytes(32)); - + if (! await _transactionsLookups.IsAmountAvailableAsync(createOpenChannelIn.FundingAmount)) + throw new InvalidOperationException("The amount is not available"); //TODO David change this to return false rather than exception? + + OpenChannel openChannel = new() + { + ChainHash = chainParameters.Chainhash, + TemporaryChannelId = new UInt256(_randomNumberGenerator.GetBytes(32)) + }; + if (createOpenChannelIn.PrivateChannel && !chainParameters.ChannelBoundariesConfig.AllowPrivateChannels) throw new ApplicationException($"Private channels are not enabled"); diff --git a/src/Lyn.Protocol/Bolt2/Wallet/IWalletTransactions.cs b/src/Lyn.Protocol/Bolt2/Wallet/IWalletTransactions.cs new file mode 100644 index 0000000..415ac16 --- /dev/null +++ b/src/Lyn.Protocol/Bolt2/Wallet/IWalletTransactions.cs @@ -0,0 +1,15 @@ +using System.Threading.Tasks; +using Lyn.Types.Bitcoin; +using Lyn.Types.Fundamental; + +namespace Lyn.Protocol.Bolt2.Wallet +{ + public interface IWalletTransactions + { + Task IsAmountAvailableAsync(Satoshis amount); + + Task GenerateTransactionForOutputAsync(TransactionOutput transactionOutput); + + Task PublishTransactionAsync(Transaction transaction); + } +} \ No newline at end of file diff --git a/src/Lyn.Protocol/Bolt2/Wallet/WalletTransactions.cs b/src/Lyn.Protocol/Bolt2/Wallet/WalletTransactions.cs new file mode 100644 index 0000000..2447586 --- /dev/null +++ b/src/Lyn.Protocol/Bolt2/Wallet/WalletTransactions.cs @@ -0,0 +1,80 @@ +using System; +using System.Net; +using System.Threading.Tasks; +using Lyn.Protocol.Common.Messages; +using Lyn.Types; +using Lyn.Types.Bitcoin; +using Lyn.Types.Fundamental; +using NBitcoin; +using Newtonsoft.Json.Linq; +using Transaction = Lyn.Types.Bitcoin.Transaction; + +namespace Lyn.Protocol.Bolt2.Wallet +{ + public class WalletTransactions : IWalletTransactions + { + private readonly ISerializationFactory _serializationFactory; + + private NBitcoin.RPC.RPCClient? _client; + + public WalletTransactions(ISerializationFactory serializationFactory) + { + _serializationFactory = serializationFactory; + } +//bcrt1qhn9gawy9vv73tlkaunaunwzea9ula0qj8pe9yn + public async Task IsAmountAvailableAsync(Satoshis amount) + { + var client = GetClient(); + + var response = await client.GetBalanceAsync(); + + return response.Satoshi.CompareTo((long)amount) > 0; + } + + public async Task GenerateTransactionForOutputAsync(TransactionOutput transactionOutput) + { + var client = GetClient(); + + var hex = GetTransactionHex(new Transaction { Outputs = new[] { transactionOutput }, Version = 2 }); + + var response = await client.SendCommandAsync("fundrawtransaction", hex); + + var r = (JObject)response.Result; + + var signedTransactionResult = await client.SendCommandAsync("signrawtransactionwithwallet", r["hex"].Value()); + + var raw = (JObject)signedTransactionResult.Result; + + return _serializationFactory.Deserialize(Hex.FromString(raw["hex"].Value())); + } + + public async Task PublishTransactionAsync(Transaction transaction) + { + var client = GetClient(); + + var result = await client.SendCommandAsync("sendrawtransaction", GetTransactionHex(transaction)); + + if (result is null) + throw new InvalidOperationException(); + } + + + private NBitcoin.RPC.RPCClient GetClient() + { + if (_client is not null) + return _client; + + var uriBuilder = new UriBuilder(new Uri("http://127.0.0.1")); + uriBuilder.Port = 18443; + + _client = new NBitcoin.RPC.RPCClient(new NetworkCredential("regtest","regtest"), uriBuilder.Uri,Network.RegTest); + + return _client; + } + + private string GetTransactionHex(Transaction transaction) + { + return Hex.ToString(_serializationFactory.Serialize(transaction)); + } + } +} \ No newline at end of file diff --git a/src/Lyn.Protocol/Bolt3/LightningKeyDerivation.cs b/src/Lyn.Protocol/Bolt3/LightningKeyDerivation.cs index f87543b..58b1bb2 100644 --- a/src/Lyn.Protocol/Bolt3/LightningKeyDerivation.cs +++ b/src/Lyn.Protocol/Bolt3/LightningKeyDerivation.cs @@ -18,10 +18,10 @@ public LightningKeyDerivation() public UInt256 DeriveChannelId(UInt256 hash, ushort index) { var hashbytes = hash.GetBytes().ToArray(); - var indexbytes = BitConverter.GetBytes(index); + var indexbytes = BitConverter.GetBytes( index); - hashbytes[30] ^= indexbytes[0]; - hashbytes[31] ^= indexbytes[1]; + hashbytes[30] ^= indexbytes[1]; //Big endian + hashbytes[31] ^= indexbytes[0]; UInt256 newChannelId = new UInt256(hashbytes); diff --git a/src/Lyn.Protocol/Bolt9/LynImplementedBoltFeatures.cs b/src/Lyn.Protocol/Bolt9/LynImplementedBoltFeatures.cs index 31547a6..ef1656a 100644 --- a/src/Lyn.Protocol/Bolt9/LynImplementedBoltFeatures.cs +++ b/src/Lyn.Protocol/Bolt9/LynImplementedBoltFeatures.cs @@ -5,7 +5,7 @@ namespace Lyn.Protocol.Bolt9 { public class LynImplementedBoltFeatures : IBoltFeatures { - private const Features FEATURES = Features.InitialRoutingSync | Features.OptionStaticRemotekey;//| Features.GossipQueries; this will need to be added back when the gossip queries are fully supported + private const Features FEATURES = Features.InitialRoutingSync;//| Features.OptionStaticRemotekey;| Features.GossipQueries; this will need to be added back when the gossip queries are fully supported private readonly byte[] _bytes; private readonly BitArray _FeaturesBitArray; diff --git a/src/Lyn.Protocol/Common/DefaultIoCRegistrations.cs b/src/Lyn.Protocol/Common/DefaultIoCRegistrations.cs index 231607c..c04ee97 100644 --- a/src/Lyn.Protocol/Common/DefaultIoCRegistrations.cs +++ b/src/Lyn.Protocol/Common/DefaultIoCRegistrations.cs @@ -8,12 +8,14 @@ using Lyn.Protocol.Bolt2.ChannelEstablishment; using Lyn.Protocol.Bolt2.ChannelEstablishment.Messages; using Lyn.Protocol.Bolt2.ChannelEstablishment.Messages.TlvRecords; +using Lyn.Protocol.Bolt2.Wallet; using Lyn.Protocol.Bolt3; using Lyn.Protocol.Bolt7; using Lyn.Protocol.Bolt7.Messages; using Lyn.Protocol.Bolt8; using Lyn.Protocol.Bolt9; using Lyn.Protocol.Common.Blockchain; +using Lyn.Protocol.Common.Hashing; using Lyn.Protocol.Common.Messages; using Lyn.Protocol.Connection; using Lyn.Types.Serialization; @@ -127,6 +129,7 @@ private static IServiceCollection AddControlAndSetupMessageSupport(this IService services.AddSingleton(); //TODO Dan this is not control and setup services services.AddSingleton(); + services.AddSingleton(); return services; } diff --git a/src/Lyn.Protocol/Common/ITransactionHashCalculator.cs b/src/Lyn.Protocol/Common/Hashing/ITransactionHashCalculator.cs similarity index 84% rename from src/Lyn.Protocol/Common/ITransactionHashCalculator.cs rename to src/Lyn.Protocol/Common/Hashing/ITransactionHashCalculator.cs index 723696c..e7f7bbb 100644 --- a/src/Lyn.Protocol/Common/ITransactionHashCalculator.cs +++ b/src/Lyn.Protocol/Common/Hashing/ITransactionHashCalculator.cs @@ -1,6 +1,6 @@ using Lyn.Types.Bitcoin; -namespace Lyn.Protocol.Common +namespace Lyn.Protocol.Common.Hashing { public interface ITransactionHashCalculator { diff --git a/src/Lyn.Protocol/Common/TransactionHashCalculator.cs b/src/Lyn.Protocol/Common/Hashing/TransactionHashCalculator.cs similarity index 92% rename from src/Lyn.Protocol/Common/TransactionHashCalculator.cs rename to src/Lyn.Protocol/Common/Hashing/TransactionHashCalculator.cs index 195396a..cf9c012 100644 --- a/src/Lyn.Protocol/Common/TransactionHashCalculator.cs +++ b/src/Lyn.Protocol/Common/Hashing/TransactionHashCalculator.cs @@ -1,10 +1,8 @@ -using System; -using System.Buffers; -using Lyn.Protocol.Common.Hashing; +using System.Buffers; using Lyn.Types.Bitcoin; using Lyn.Types.Serialization; -namespace Lyn.Protocol.Common +namespace Lyn.Protocol.Common.Hashing { public class TransactionHashCalculator : ITransactionHashCalculator { diff --git a/src/Lyn.Types/Hex.cs b/src/Lyn.Types/Hex.cs index 914cfe7..d162f40 100644 --- a/src/Lyn.Types/Hex.cs +++ b/src/Lyn.Types/Hex.cs @@ -19,22 +19,22 @@ public static byte[] FromString(string hex) public static string ToString(ReadOnlySpan span) { - return $"0x{Convert.ToHexString(span).ToLower()}"; + return Convert.ToHexString(span).ToLower(); } public static string ToString(Span span) { - return $"0x{Convert.ToHexString(span).ToLower()}"; + return Convert.ToHexString(span).ToLower(); } public static string ToString(IEnumerable arr) { - return $"0x{Convert.ToHexString(arr.ToArray()).ToLower()}"; + return Convert.ToHexString(arr.ToArray()).ToLower(); } public static string ToString(byte[] arr) { - return $"0x{Convert.ToHexString(arr).ToLower()}"; + return Convert.ToHexString(arr).ToLower(); } } } \ No newline at end of file From 2a6b5b94e2c0f9b2cb0453531ae523bd8f1e11f2 Mon Sep 17 00:00:00 2001 From: TheDude Date: Tue, 19 Oct 2021 14:57:42 +0100 Subject: [PATCH 05/13] Add missing changes --- .../Bolt2/ChannelEstablishment/Entities/ChannelCandidate.cs | 2 ++ src/Lyn.Protocol/Lyn.Protocol.csproj | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/src/Lyn.Protocol/Bolt2/ChannelEstablishment/Entities/ChannelCandidate.cs b/src/Lyn.Protocol/Bolt2/ChannelEstablishment/Entities/ChannelCandidate.cs index 7e0182f..d9dc78d 100644 --- a/src/Lyn.Protocol/Bolt2/ChannelEstablishment/Entities/ChannelCandidate.cs +++ b/src/Lyn.Protocol/Bolt2/ChannelEstablishment/Entities/ChannelCandidate.cs @@ -30,5 +30,7 @@ public class ChannelCandidate public Transaction? RemoteCommitmentTransaction { get; set; } public Transaction? LocalCommitmentTransaction { get; set; } + + public Transaction? FundingTransaction { get; set; } } } \ No newline at end of file diff --git a/src/Lyn.Protocol/Lyn.Protocol.csproj b/src/Lyn.Protocol/Lyn.Protocol.csproj index 4148e53..fc9a502 100644 --- a/src/Lyn.Protocol/Lyn.Protocol.csproj +++ b/src/Lyn.Protocol/Lyn.Protocol.csproj @@ -21,4 +21,8 @@ + + + + \ No newline at end of file From 6a8123cf8b0eb5cd3c89d7bf5f2fefb5a29e007b Mon Sep 17 00:00:00 2001 From: TheDude Date: Thu, 21 Oct 2021 10:44:40 +0100 Subject: [PATCH 06/13] Started handling funding locked and creating payment channel --- src/Lyn.Protocol/Bolt1/Entities/Peer.cs | 5 + .../AcceptChannelMessageService.cs | 11 +-- .../Entities/ChannelCandidate.cs | 6 +- .../FundingLockedMessageService.cs | 92 +++++++++++++++++++ .../FundingSignedMessageService.cs | 7 +- .../Messages/FundingLockedSerializer.cs | 28 ++++++ .../Bolt2/Entities/PaymentChannel.cs | 78 ++++++++++++++++ .../IPaymentChannelRepository.cs | 15 +++ .../InMemoryPaymentChannelRepository.cs | 37 ++++++++ .../Common/DefaultIoCRegistrations.cs | 4 + 10 files changed, 271 insertions(+), 12 deletions(-) create mode 100644 src/Lyn.Protocol/Bolt2/ChannelEstablishment/FundingLockedMessageService.cs create mode 100644 src/Lyn.Protocol/Bolt2/ChannelEstablishment/Messages/FundingLockedSerializer.cs create mode 100644 src/Lyn.Protocol/Bolt2/Entities/PaymentChannel.cs create mode 100644 src/Lyn.Protocol/Bolt2/NormalOperations/IPaymentChannelRepository.cs create mode 100644 src/Lyn.Protocol/Bolt2/NormalOperations/InMemoryPaymentChannelRepository.cs diff --git a/src/Lyn.Protocol/Bolt1/Entities/Peer.cs b/src/Lyn.Protocol/Bolt1/Entities/Peer.cs index 1f2ec1d..5d4882a 100644 --- a/src/Lyn.Protocol/Bolt1/Entities/Peer.cs +++ b/src/Lyn.Protocol/Bolt1/Entities/Peer.cs @@ -19,5 +19,10 @@ public bool SupportsFeature(Features feature) { return (Features & Features.OptionUpfrontShutdownScript) != 0; } + + public bool MutuallySupportedFeature(Features feature) + { + return (MutuallySupportedFeatures & Features.OptionUpfrontShutdownScript) != 0; + } } } \ No newline at end of file diff --git a/src/Lyn.Protocol/Bolt2/ChannelEstablishment/AcceptChannelMessageService.cs b/src/Lyn.Protocol/Bolt2/ChannelEstablishment/AcceptChannelMessageService.cs index d16a5d7..18f7f03 100644 --- a/src/Lyn.Protocol/Bolt2/ChannelEstablishment/AcceptChannelMessageService.cs +++ b/src/Lyn.Protocol/Bolt2/ChannelEstablishment/AcceptChannelMessageService.cs @@ -1,7 +1,4 @@ -using System; -using System.Buffers; -using System.Collections.Generic; -using System.Linq; +using System.Collections.Generic; using Lyn.Protocol.Bolt2.ChannelEstablishment.Entities; using Lyn.Protocol.Bolt2.ChannelEstablishment.Messages; using Lyn.Protocol.Bolt3; @@ -138,7 +135,7 @@ public async Task ProcessMessageAsync(PeerMessage ProcessMessageAsync(PeerMessage(), Opener = channelCandidate.ChannelOpener, Side = ChannelSide.Remote, + CommitmentNumber = 0, FundingTxout = inPoint, DustLimitSatoshis = channelCandidate.AcceptChannel.DustLimitSatoshis, diff --git a/src/Lyn.Protocol/Bolt2/ChannelEstablishment/Entities/ChannelCandidate.cs b/src/Lyn.Protocol/Bolt2/ChannelEstablishment/Entities/ChannelCandidate.cs index d9dc78d..9a99d54 100644 --- a/src/Lyn.Protocol/Bolt2/ChannelEstablishment/Entities/ChannelCandidate.cs +++ b/src/Lyn.Protocol/Bolt2/ChannelEstablishment/Entities/ChannelCandidate.cs @@ -1,10 +1,6 @@ using Lyn.Protocol.Bolt2.ChannelEstablishment.Messages; -using Lyn.Protocol.Bolt2.ChannelEstablishment.Messages.TlvRecords; -using Lyn.Protocol.Bolt2.Configuration; using Lyn.Protocol.Bolt3.Types; using Lyn.Types.Bitcoin; -using Lyn.Types.Bolt; -using Lyn.Types.Fundamental; namespace Lyn.Protocol.Bolt2.ChannelEstablishment.Entities { @@ -32,5 +28,7 @@ public class ChannelCandidate public Transaction? LocalCommitmentTransaction { get; set; } public Transaction? FundingTransaction { get; set; } + + public bool FundingLockedSent { get; set; } } } \ No newline at end of file diff --git a/src/Lyn.Protocol/Bolt2/ChannelEstablishment/FundingLockedMessageService.cs b/src/Lyn.Protocol/Bolt2/ChannelEstablishment/FundingLockedMessageService.cs new file mode 100644 index 0000000..df05975 --- /dev/null +++ b/src/Lyn.Protocol/Bolt2/ChannelEstablishment/FundingLockedMessageService.cs @@ -0,0 +1,92 @@ +using System; +using System.Threading.Tasks; +using Lyn.Protocol.Bolt2.ChannelEstablishment.Messages; +using Lyn.Protocol.Bolt2.Entities; +using Lyn.Protocol.Bolt2.NormalOperations; +using Lyn.Protocol.Bolt3; +using Lyn.Protocol.Common.Messages; +using Lyn.Protocol.Connection; +using Lyn.Types.Bitcoin; +using Microsoft.Extensions.Logging; + +namespace Lyn.Protocol.Bolt2.ChannelEstablishment +{ + public class FundingLockedMessageService : IBoltMessageService + { + private readonly ILogger _logger; + private readonly IChannelCandidateRepository _channelCandidateRepository; + private readonly IPaymentChannelRepository _paymentChannelRepository; + private readonly ISecretStore _secretStore; + private readonly ILightningKeyDerivation _lightningKeyDerivation; + + public FundingLockedMessageService(ILogger logger, + IChannelCandidateRepository channelCandidateRepository, IPaymentChannelRepository paymentChannelRepository, + ISecretStore secretStore, ILightningKeyDerivation lightningKeyDerivation) + { + _logger = logger; + _channelCandidateRepository = channelCandidateRepository; + _paymentChannelRepository = paymentChannelRepository; + _secretStore = secretStore; + _lightningKeyDerivation = lightningKeyDerivation; + } + + public async Task ProcessMessageAsync(PeerMessage message) + { + var channelCandidate = await _channelCandidateRepository.GetAsync(message.MessagePayload.ChannelId); + + if (channelCandidate == null) + { + return new ErrorCloseChannelResponse(message.MessagePayload.ChannelId, + "open channel is in an invalid state"); + } + + channelCandidate.FundingLocked = message.MessagePayload; + + if (!channelCandidate.FundingLockedSent) + { + await _channelCandidateRepository.UpdateAsync(channelCandidate); //Waiting for confirmation from our side as well + return new EmptySuccessResponse(); + } + + //Time to create the payment channel + PaymentChannel paymentChannel = new PaymentChannel( + channelCandidate.ChannelId ?? throw new InvalidOperationException(), + channelCandidate.FundingSignedRemote?.Signature ?? throw new InvalidOperationException(), + message.MessagePayload.NextPerCommitmentPoint ?? throw new InvalidOperationException(), + new[] + { + channelCandidate.AcceptChannel?.FirstPerCommitmentPoint ?? throw new InvalidOperationException() + }, + channelCandidate.OpenChannel?.FundingSatoshis ?? throw new InvalidOperationException(), + new OutPoint + { + Hash = channelCandidate.FundingCreated?.FundingTxid ?? throw new InvalidOperationException(), + Index = channelCandidate.FundingCreated.FundingOutputIndex ?? throw new InvalidOperationException() + }, + channelCandidate.OpenChannel.DustLimitSatoshis, + channelCandidate.AcceptChannel.DustLimitSatoshis ?? throw new InvalidOperationException(), + channelCandidate.OpenChannel.FeeratePerKw, + channelCandidate.OpenChannel.FundingPubkey, + channelCandidate.AcceptChannel.FundingPubkey ?? throw new InvalidOperationException(), + channelCandidate.OpenChannel.PushMsat, + channelCandidate.OpenChannel.GetBasePoints(), + channelCandidate.AcceptChannel.GetBasePoints() + ); + + await _paymentChannelRepository.AddNewPaymentChannelAsync(paymentChannel); + + //TODO update gossip repo with new channel + + var seed = _secretStore.GetSeed(); + var secrets = _lightningKeyDerivation.DeriveSecrets(seed); + + var fundingLockedResponse = new FundingLocked + { + ChannelId = channelCandidate.FundingLocked.ChannelId, + NextPerCommitmentPoint = _lightningKeyDerivation.PerCommitmentPoint(secrets.Shaseed, 1) + }; + + return new SuccessWithOutputResponse(new BoltMessage{Payload = fundingLockedResponse}); + } + } +} \ No newline at end of file diff --git a/src/Lyn.Protocol/Bolt2/ChannelEstablishment/FundingSignedMessageService.cs b/src/Lyn.Protocol/Bolt2/ChannelEstablishment/FundingSignedMessageService.cs index a6f680f..9c0713b 100644 --- a/src/Lyn.Protocol/Bolt2/ChannelEstablishment/FundingSignedMessageService.cs +++ b/src/Lyn.Protocol/Bolt2/ChannelEstablishment/FundingSignedMessageService.cs @@ -82,8 +82,8 @@ public async Task ProcessMessageAsync(PeerMessage ProcessMessageAsync(PeerMessage + { + public int Serialize(FundingLocked typeInstance, IBufferWriter writer, ProtocolTypeSerializerOptions? options = null) + { + var size = 0; + + size += writer.WriteUint256(typeInstance.ChannelId); + size += writer.WriteBytes(typeInstance.NextPerCommitmentPoint); + + return size; + } + + public FundingLocked Deserialize(ref SequenceReader reader, ProtocolTypeSerializerOptions? options = null) + { + return new FundingLocked + { + ChannelId = reader.ReadUint256(), + NextPerCommitmentPoint = reader.ReadBytes(PublicKey.LENGTH) + }; + } + } +} \ No newline at end of file diff --git a/src/Lyn.Protocol/Bolt2/Entities/PaymentChannel.cs b/src/Lyn.Protocol/Bolt2/Entities/PaymentChannel.cs new file mode 100644 index 0000000..cd2a4d6 --- /dev/null +++ b/src/Lyn.Protocol/Bolt2/Entities/PaymentChannel.cs @@ -0,0 +1,78 @@ +using Lyn.Protocol.Bolt3.Types; +using Lyn.Types.Bitcoin; +using Lyn.Types.Bolt; +using Lyn.Types.Fundamental; + +namespace Lyn.Protocol.Bolt2.Entities +{ + public class PaymentChannel + { + public PaymentChannel(UInt256 channelId,CompressedSignature compressedSignature, PublicKey perCommitmentPoint, + PublicKey[] previousPerCommitmentPoints, Satoshis fundingSatoshis, OutPoint inPoint, Satoshis localDustLimitSatoshis, + Satoshis remoteDustLimitSatoshis, Satoshis feeratePerKw, PublicKey localFundingKey, PublicKey remoteFundingKey, + MiliSatoshis pushMsat, Basepoints localBasePoints, Basepoints remoteBasePoints) + { + ChannelId = channelId; + PerCommitmentPoint = perCommitmentPoint; + PreviousPerCommitmentPoints = previousPerCommitmentPoints; + FundingSatoshis = fundingSatoshis; + InPoint = inPoint; + LocalDustLimitSatoshis = localDustLimitSatoshis; + RemoteDustLimitSatoshis = remoteDustLimitSatoshis; + FeeratePerKw = feeratePerKw; + LocalFundingKey = localFundingKey; + RemoteFundingKey = remoteFundingKey; + PushMsat = pushMsat; + LocalBasePoints = localBasePoints; + RemoteBasePoints = remoteBasePoints; + CompressedSignature = compressedSignature; + } + + public UInt256 ChannelId { get; set; } + + public ShortChannelId ShortChannelId { get; set; } //TODO David + + public PublicKey PerCommitmentPoint { get; set; } + + public PublicKey[] PreviousPerCommitmentPoints { get; set; } //TODO David + + public CompressedSignature CompressedSignature { get; set; } + + + + public Satoshis FundingSatoshis { get; set; } + + public ulong CommitmentNumber { get; set; } + + public OutPoint InPoint { get; set; } + + public Satoshis LocalDustLimitSatoshis { get; set; } + public Satoshis RemoteDustLimitSatoshis { get; set; } + + public Satoshis FeeratePerKw { get; set; } + + public PublicKey LocalFundingKey { get; set; } + public PublicKey RemoteFundingKey { get; set; } + + public bool OptionAnchorOutputs { get; set; } + + public MiliSatoshis PushMsat { get; set; } + + public ushort LocalToSelfDelay { get; set; } + public ushort RemoteToSelfDelay { get; set; } + + public bool WasChannelInitiatedLocally { get; set; } + + public ulong CnObscurer { get; set; } + + + public Basepoints LocalBasePoints { get; set; } + public Basepoints RemoteBasePoints { get; set; } + + + // public Keyset Keyset { get; set; } + // public MiliSatoshis SelfPayMsat { get; set; } + // public MiliSatoshis OtherPayMsat { get; set; } + // public List Htlcs { get; set; } + } +} \ No newline at end of file diff --git a/src/Lyn.Protocol/Bolt2/NormalOperations/IPaymentChannelRepository.cs b/src/Lyn.Protocol/Bolt2/NormalOperations/IPaymentChannelRepository.cs new file mode 100644 index 0000000..1bbd6df --- /dev/null +++ b/src/Lyn.Protocol/Bolt2/NormalOperations/IPaymentChannelRepository.cs @@ -0,0 +1,15 @@ +using System; +using System.Threading.Tasks; +using Lyn.Protocol.Bolt2.Entities; +using Lyn.Types.Bitcoin; +using Lyn.Types.Bolt; + +namespace Lyn.Protocol.Bolt2.NormalOperations +{ + public interface IPaymentChannelRepository + { + Task AddNewPaymentChannelAsync(PaymentChannel paymentChannel); + + Task TryGetPaymentChannelAsync(UInt256 channelId); + } +} \ No newline at end of file diff --git a/src/Lyn.Protocol/Bolt2/NormalOperations/InMemoryPaymentChannelRepository.cs b/src/Lyn.Protocol/Bolt2/NormalOperations/InMemoryPaymentChannelRepository.cs new file mode 100644 index 0000000..d2c3134 --- /dev/null +++ b/src/Lyn.Protocol/Bolt2/NormalOperations/InMemoryPaymentChannelRepository.cs @@ -0,0 +1,37 @@ +using System.Collections.Concurrent; +using System.Threading.Tasks; +using Lyn.Protocol.Bolt2.Entities; +using Lyn.Types.Bitcoin; + +namespace Lyn.Protocol.Bolt2.NormalOperations +{ + public class InMemoryPaymentChannelRepository : IPaymentChannelRepository + { + private ConcurrentDictionary _channels; + + public InMemoryPaymentChannelRepository() + { + _channels = new ConcurrentDictionary(); + } + + public Task AddNewPaymentChannelAsync(PaymentChannel paymentChannel) + { + var success = _channels.TryAdd(paymentChannel.ChannelId, paymentChannel); + + if (!success) + { + //TODO David + } + + return Task.CompletedTask; + } + + public Task TryGetPaymentChannelAsync(UInt256 channelId) + { + return _channels.ContainsKey(channelId) + ? Task.FromResult(_channels[channelId]) + : Task.FromResult(null); + + } + } +} \ No newline at end of file diff --git a/src/Lyn.Protocol/Common/DefaultIoCRegistrations.cs b/src/Lyn.Protocol/Common/DefaultIoCRegistrations.cs index c04ee97..79c3009 100644 --- a/src/Lyn.Protocol/Common/DefaultIoCRegistrations.cs +++ b/src/Lyn.Protocol/Common/DefaultIoCRegistrations.cs @@ -8,6 +8,7 @@ using Lyn.Protocol.Bolt2.ChannelEstablishment; using Lyn.Protocol.Bolt2.ChannelEstablishment.Messages; using Lyn.Protocol.Bolt2.ChannelEstablishment.Messages.TlvRecords; +using Lyn.Protocol.Bolt2.NormalOperations; using Lyn.Protocol.Bolt2.Wallet; using Lyn.Protocol.Bolt3; using Lyn.Protocol.Bolt7; @@ -114,6 +115,8 @@ private static IServiceCollection AddNetworkMessageSerialization(this IServiceCo services.AddSingleton>(); services.AddSingleton>(); services.AddSingleton>(); + services.AddSingleton>(); + return services; } @@ -130,6 +133,7 @@ private static IServiceCollection AddControlAndSetupMessageSupport(this IService services.AddSingleton(); //TODO Dan this is not control and setup services services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); return services; } From 37fd2ee83a23e011938fdd3d43068670b13cd22c Mon Sep 17 00:00:00 2001 From: TheDude Date: Thu, 21 Oct 2021 10:55:37 +0100 Subject: [PATCH 07/13] Added some logging on funding locked service --- .../Entities/ChannelCandidate.cs | 3 +-- .../FundingLockedMessageService.cs | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/Lyn.Protocol/Bolt2/ChannelEstablishment/Entities/ChannelCandidate.cs b/src/Lyn.Protocol/Bolt2/ChannelEstablishment/Entities/ChannelCandidate.cs index 9a99d54..ed6abea 100644 --- a/src/Lyn.Protocol/Bolt2/ChannelEstablishment/Entities/ChannelCandidate.cs +++ b/src/Lyn.Protocol/Bolt2/ChannelEstablishment/Entities/ChannelCandidate.cs @@ -15,6 +15,7 @@ public class ChannelCandidate public AcceptChannel? AcceptChannel { get; set; } public FundingCreated? FundingCreated { get; set; } public FundingLocked? FundingLocked { get; set; } + public FundingSigned? FundingSignedLocal { get; set; } public FundingSigned? FundingSignedRemote { get; set; } public byte[]? OpenChannelUpfrontShutdownScript { get; set; } @@ -28,7 +29,5 @@ public class ChannelCandidate public Transaction? LocalCommitmentTransaction { get; set; } public Transaction? FundingTransaction { get; set; } - - public bool FundingLockedSent { get; set; } } } \ No newline at end of file diff --git a/src/Lyn.Protocol/Bolt2/ChannelEstablishment/FundingLockedMessageService.cs b/src/Lyn.Protocol/Bolt2/ChannelEstablishment/FundingLockedMessageService.cs index df05975..b1a00ee 100644 --- a/src/Lyn.Protocol/Bolt2/ChannelEstablishment/FundingLockedMessageService.cs +++ b/src/Lyn.Protocol/Bolt2/ChannelEstablishment/FundingLockedMessageService.cs @@ -4,6 +4,7 @@ using Lyn.Protocol.Bolt2.Entities; using Lyn.Protocol.Bolt2.NormalOperations; using Lyn.Protocol.Bolt3; +using Lyn.Protocol.Bolt3.Types; using Lyn.Protocol.Common.Messages; using Lyn.Protocol.Connection; using Lyn.Types.Bitcoin; @@ -32,19 +33,25 @@ public FundingLockedMessageService(ILogger logger, public async Task ProcessMessageAsync(PeerMessage message) { + _logger.LogDebug("Processing funding locked from peer"); var channelCandidate = await _channelCandidateRepository.GetAsync(message.MessagePayload.ChannelId); if (channelCandidate == null) { + _logger.LogWarning($"Channel candidate not found in the repository for channel id {message.MessagePayload.ChannelId}"); + return new ErrorCloseChannelResponse(message.MessagePayload.ChannelId, "open channel is in an invalid state"); } channelCandidate.FundingLocked = message.MessagePayload; - if (!channelCandidate.FundingLockedSent) + if (channelCandidate.ChannelOpener != ChannelSide.Local) // We will be publishing to block chain in that case { + _logger.LogDebug("Confirmation of funding transaction not received yet"); + await _channelCandidateRepository.UpdateAsync(channelCandidate); //Waiting for confirmation from our side as well + return new EmptySuccessResponse(); } @@ -75,6 +82,8 @@ public async Task ProcessMessageAsync(PeerMessage ProcessMessageAsync(PeerMessage Date: Thu, 21 Oct 2021 11:19:00 +0100 Subject: [PATCH 08/13] Added channel reestablish message and serializer --- .../Messages/ChannelReestablish.cs | 32 +++++++++++++++++++ .../Messages/ChannelReestablishSerializer.cs | 31 ++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 src/Lyn.Protocol/Bolt2/ChannelEstablishment/Messages/ChannelReestablish.cs create mode 100644 src/Lyn.Protocol/Bolt2/ChannelEstablishment/Messages/ChannelReestablishSerializer.cs diff --git a/src/Lyn.Protocol/Bolt2/ChannelEstablishment/Messages/ChannelReestablish.cs b/src/Lyn.Protocol/Bolt2/ChannelEstablishment/Messages/ChannelReestablish.cs new file mode 100644 index 0000000..53a44ac --- /dev/null +++ b/src/Lyn.Protocol/Bolt2/ChannelEstablishment/Messages/ChannelReestablish.cs @@ -0,0 +1,32 @@ +using Lyn.Protocol.Common.Messages; +using Lyn.Types.Bitcoin; +using Lyn.Types.Fundamental; + +namespace Lyn.Protocol.Bolt2.ChannelEstablishment.Messages +{ + public class ChannelReestablish : MessagePayload + { + public ChannelReestablish(UInt256 channelId,ulong nextCommitmentNumber,ulong nextRevocationNumber, PublicKey lastPerCommitmentSecret, PublicKey currentPerCommitmentPoint) + { + ChannelId = channelId; + NextCommitmentNumber = nextCommitmentNumber; + NextRevocationNumber = nextRevocationNumber; + LastPerCommitmentSecret = lastPerCommitmentSecret; + CurrentPerCommitmentPoint = currentPerCommitmentPoint; + } + + public override MessageType MessageType => MessageType.ChannelReestablish; + + + public UInt256 ChannelId { get; set; } + + public ulong NextCommitmentNumber { get; set; } + + public ulong NextRevocationNumber { get; set; } + + public PublicKey LastPerCommitmentSecret { get; set; } + + public PublicKey CurrentPerCommitmentPoint { get; set; } + + } +} \ No newline at end of file diff --git a/src/Lyn.Protocol/Bolt2/ChannelEstablishment/Messages/ChannelReestablishSerializer.cs b/src/Lyn.Protocol/Bolt2/ChannelEstablishment/Messages/ChannelReestablishSerializer.cs new file mode 100644 index 0000000..e716df6 --- /dev/null +++ b/src/Lyn.Protocol/Bolt2/ChannelEstablishment/Messages/ChannelReestablishSerializer.cs @@ -0,0 +1,31 @@ +using System.Buffers; +using Lyn.Types.Fundamental; +using Lyn.Types.Serialization; + +namespace Lyn.Protocol.Bolt2.ChannelEstablishment.Messages +{ + public class ChannelReestablishSerializer : IProtocolTypeSerializer + { + public int Serialize(ChannelReestablish typeInstance, IBufferWriter writer, ProtocolTypeSerializerOptions? options = null) + { + var size = 0; + + size += writer.WriteUint256(typeInstance.ChannelId); + size += writer.WriteULong(typeInstance.NextCommitmentNumber, true); + size += writer.WriteULong(typeInstance.NextRevocationNumber, true); + size += writer.WriteBytes(typeInstance.CurrentPerCommitmentPoint); + size += writer.WriteBytes(typeInstance.LastPerCommitmentSecret); + + return size; + } + + public ChannelReestablish Deserialize(ref SequenceReader reader, ProtocolTypeSerializerOptions? options = null) + { + return new ChannelReestablish(reader.ReadUint256(), + reader.ReadULong(true), + reader.ReadULong(true), + reader.ReadBytes(PublicKey.LENGTH), + reader.ReadBytes(PublicKey.LENGTH)); + } + } +} \ No newline at end of file From a930a75a22d99aa82a2104589cddbc8777f82e9e Mon Sep 17 00:00:00 2001 From: TheDude Date: Thu, 21 Oct 2021 16:45:18 +0100 Subject: [PATCH 09/13] Started work on channel reestablishment --- .../FundingLockedMessageService.cs | 12 ++- .../Messages/ChannelReestablish.cs | 32 -------- .../Bolt2/Entities/PaymentChannel.cs | 6 +- .../ChannelReestablishMessageService.cs | 73 +++++++++++++++++++ .../Messages/ChannelReestablish.cs | 22 ++++-- .../Messages/ChannelReestablishSerializer.cs | 8 +- src/Lyn.Types/Fundamental/PrivateKey.cs | 6 +- 7 files changed, 111 insertions(+), 48 deletions(-) delete mode 100644 src/Lyn.Protocol/Bolt2/ChannelEstablishment/Messages/ChannelReestablish.cs create mode 100644 src/Lyn.Protocol/Bolt2/MessageRetransmission/ChannelReestablishMessageService.cs rename src/Lyn.Protocol/Bolt2/{ChannelEstablishment => MessageRetransmission}/Messages/ChannelReestablishSerializer.cs (76%) diff --git a/src/Lyn.Protocol/Bolt2/ChannelEstablishment/FundingLockedMessageService.cs b/src/Lyn.Protocol/Bolt2/ChannelEstablishment/FundingLockedMessageService.cs index b1a00ee..6a59d9f 100644 --- a/src/Lyn.Protocol/Bolt2/ChannelEstablishment/FundingLockedMessageService.cs +++ b/src/Lyn.Protocol/Bolt2/ChannelEstablishment/FundingLockedMessageService.cs @@ -34,6 +34,16 @@ public FundingLockedMessageService(ILogger logger, public async Task ProcessMessageAsync(PeerMessage message) { _logger.LogDebug("Processing funding locked from peer"); + + var existingChannel = + await _paymentChannelRepository.TryGetPaymentChannelAsync(message.MessagePayload.ChannelId); //TODO validate the message before using it + + if (existingChannel != null) + { + // this was a reconnection process for a new channel can just ignore the message + return new EmptySuccessResponse(); + } + var channelCandidate = await _channelCandidateRepository.GetAsync(message.MessagePayload.ChannelId); if (channelCandidate == null) @@ -92,7 +102,7 @@ public async Task ProcessMessageAsync(PeerMessage MessageType.ChannelReestablish; - - - public UInt256 ChannelId { get; set; } - - public ulong NextCommitmentNumber { get; set; } - - public ulong NextRevocationNumber { get; set; } - - public PublicKey LastPerCommitmentSecret { get; set; } - - public PublicKey CurrentPerCommitmentPoint { get; set; } - - } -} \ No newline at end of file diff --git a/src/Lyn.Protocol/Bolt2/Entities/PaymentChannel.cs b/src/Lyn.Protocol/Bolt2/Entities/PaymentChannel.cs index cd2a4d6..9caf89e 100644 --- a/src/Lyn.Protocol/Bolt2/Entities/PaymentChannel.cs +++ b/src/Lyn.Protocol/Bolt2/Entities/PaymentChannel.cs @@ -36,14 +36,16 @@ public PaymentChannel(UInt256 channelId,CompressedSignature compressedSignature, public PublicKey[] PreviousPerCommitmentPoints { get; set; } //TODO David + public Secret[] PreviousPerCommitmentSecrets { get; set; } + public CompressedSignature CompressedSignature { get; set; } public Satoshis FundingSatoshis { get; set; } - public ulong CommitmentNumber { get; set; } - + public ulong LocalCommitmentNumber { get; set; } + public ulong RemoteCommitmentNumber { get; set; } public OutPoint InPoint { get; set; } public Satoshis LocalDustLimitSatoshis { get; set; } diff --git a/src/Lyn.Protocol/Bolt2/MessageRetransmission/ChannelReestablishMessageService.cs b/src/Lyn.Protocol/Bolt2/MessageRetransmission/ChannelReestablishMessageService.cs new file mode 100644 index 0000000..2e8cfae --- /dev/null +++ b/src/Lyn.Protocol/Bolt2/MessageRetransmission/ChannelReestablishMessageService.cs @@ -0,0 +1,73 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Lyn.Protocol.Bolt2.ChannelEstablishment.Messages; +using Lyn.Protocol.Bolt2.Entities; +using Lyn.Protocol.Bolt2.MessageRetransmission.Messages; +using Lyn.Protocol.Bolt2.NormalOperations; +using Lyn.Protocol.Bolt3; +using Lyn.Protocol.Common.Messages; +using Lyn.Protocol.Connection; +using Microsoft.Extensions.Logging; + +namespace Lyn.Protocol.Bolt2.MessageRetransmission +{ + public class ChannelReestablishMessageService : IBoltMessageService + { + private readonly ILogger _logger; + private readonly IPaymentChannelRepository _channelRepository; + private readonly ISecretStore _secretStore; + private readonly ILightningKeyDerivation _lightningKeyDerivation; + + public ChannelReestablishMessageService(ILogger logger, + IPaymentChannelRepository channelRepository, ISecretStore secretStore, ILightningKeyDerivation lightningKeyDerivation) + { + _logger = logger; + _channelRepository = channelRepository; + _secretStore = secretStore; + _lightningKeyDerivation = lightningKeyDerivation; + } + + public async Task ProcessMessageAsync(PeerMessage message) + { + var paymentChannel = await _channelRepository.TryGetPaymentChannelAsync(message.MessagePayload.ChannelId); + + if (paymentChannel is null) + { + _logger.LogError("Payment channel not found for channel id {message.MessagePayload.ChannelId} unable to reestablish connection"); + + return new ErrorCloseChannelResponse(message.MessagePayload.ChannelId, "Channel not found"); + } + + + if (paymentChannel.PerCommitmentPoint.Equals(message.MessagePayload.MyCurrentPerCommitmentPoint)) + { + } + + var seed = _secretStore.GetSeed(); + var secrets = _lightningKeyDerivation.DeriveSecrets(seed); + + var currentPoint = _lightningKeyDerivation.PerCommitmentPoint(secrets.Shaseed, + paymentChannel.LocalCommitmentNumber + 1); //TODO missing anchor outputs and remote static support here + + var lastKnownSecret = paymentChannel.PreviousPerCommitmentSecrets.Last(); + + var responseMessages = new List { new ChannelReestablish(paymentChannel.ChannelId, paymentChannel.LocalCommitmentNumber + 1, + paymentChannel.RemoteCommitmentNumber,currentPoint, lastKnownSecret)}; + + if (message.MessagePayload.NextCommitmentNumber == 1 && paymentChannel.LocalCommitmentNumber == 0) + { + responseMessages.Add(new FundingLocked + { + ChannelId = paymentChannel.ChannelId, + NextPerCommitmentPoint = _lightningKeyDerivation + .PerCommitmentPoint(secrets.Shaseed, paymentChannel.LocalCommitmentNumber + 1) + }); + } + + + return new SuccessWithOutputResponse( + responseMessages.Select(_ => new BoltMessage { Payload = _ }).ToArray()); + } + } +} \ No newline at end of file diff --git a/src/Lyn.Protocol/Bolt2/MessageRetransmission/Messages/ChannelReestablish.cs b/src/Lyn.Protocol/Bolt2/MessageRetransmission/Messages/ChannelReestablish.cs index f293bd5..5ece91f 100644 --- a/src/Lyn.Protocol/Bolt2/MessageRetransmission/Messages/ChannelReestablish.cs +++ b/src/Lyn.Protocol/Bolt2/MessageRetransmission/Messages/ChannelReestablish.cs @@ -1,18 +1,26 @@ -using Lyn.Protocol.Bolt1.Messages; using Lyn.Protocol.Common.Messages; using Lyn.Types.Bitcoin; -using Lyn.Types.Bolt; using Lyn.Types.Fundamental; namespace Lyn.Protocol.Bolt2.MessageRetransmission.Messages { public class ChannelReestablish : MessagePayload { + public ChannelReestablish(UInt256 channelId, ulong nextCommitmentNumber, ulong nextRevocationNumber, + PublicKey myCurrentPerCommitmentPoint, Secret yourLastPerCommitmentSecret) + { + ChannelId = channelId; + NextCommitmentNumber = nextCommitmentNumber; + NextRevocationNumber = nextRevocationNumber; + YourLastPerCommitmentSecret = yourLastPerCommitmentSecret; + MyCurrentPerCommitmentPoint = myCurrentPerCommitmentPoint; + } + public override MessageType MessageType => MessageType.ChannelReestablish; - public UInt256? ChannelId { get; set; } - public ulong? NextCommitmentNumber { get; set; } - public ulong? NextRevocationNumber { get; set; } - public Secret? YourLastPerCommitmentSecret { get; set; } - public PublicKey? MyCurrentPerCommitmentPoint { get; set; } + public UInt256 ChannelId { get; set; } + public ulong NextCommitmentNumber { get; set; } + public ulong NextRevocationNumber { get; set; } + public Secret YourLastPerCommitmentSecret { get; set; } + public PublicKey MyCurrentPerCommitmentPoint { get; set; } } } \ No newline at end of file diff --git a/src/Lyn.Protocol/Bolt2/ChannelEstablishment/Messages/ChannelReestablishSerializer.cs b/src/Lyn.Protocol/Bolt2/MessageRetransmission/Messages/ChannelReestablishSerializer.cs similarity index 76% rename from src/Lyn.Protocol/Bolt2/ChannelEstablishment/Messages/ChannelReestablishSerializer.cs rename to src/Lyn.Protocol/Bolt2/MessageRetransmission/Messages/ChannelReestablishSerializer.cs index e716df6..8a9c1f2 100644 --- a/src/Lyn.Protocol/Bolt2/ChannelEstablishment/Messages/ChannelReestablishSerializer.cs +++ b/src/Lyn.Protocol/Bolt2/MessageRetransmission/Messages/ChannelReestablishSerializer.cs @@ -2,7 +2,7 @@ using Lyn.Types.Fundamental; using Lyn.Types.Serialization; -namespace Lyn.Protocol.Bolt2.ChannelEstablishment.Messages +namespace Lyn.Protocol.Bolt2.MessageRetransmission.Messages { public class ChannelReestablishSerializer : IProtocolTypeSerializer { @@ -13,8 +13,8 @@ public int Serialize(ChannelReestablish typeInstance, IBufferWriter writer size += writer.WriteUint256(typeInstance.ChannelId); size += writer.WriteULong(typeInstance.NextCommitmentNumber, true); size += writer.WriteULong(typeInstance.NextRevocationNumber, true); - size += writer.WriteBytes(typeInstance.CurrentPerCommitmentPoint); - size += writer.WriteBytes(typeInstance.LastPerCommitmentSecret); + size += writer.WriteBytes(typeInstance.MyCurrentPerCommitmentPoint); + size += writer.WriteBytes(typeInstance.YourLastPerCommitmentSecret); return size; } @@ -25,7 +25,7 @@ public ChannelReestablish Deserialize(ref SequenceReader reader, ProtocolT reader.ReadULong(true), reader.ReadULong(true), reader.ReadBytes(PublicKey.LENGTH), - reader.ReadBytes(PublicKey.LENGTH)); + new Secret(reader.ReadBytes(PrivateKey.LENGTH).ToArray())); } } } \ No newline at end of file diff --git a/src/Lyn.Types/Fundamental/PrivateKey.cs b/src/Lyn.Types/Fundamental/PrivateKey.cs index cb842f0..cb96e7b 100644 --- a/src/Lyn.Types/Fundamental/PrivateKey.cs +++ b/src/Lyn.Types/Fundamental/PrivateKey.cs @@ -4,11 +4,13 @@ namespace Lyn.Types.Fundamental { public class PrivateKey { + public const ushort LENGTH = 32; + protected readonly byte[] _value; - + public PrivateKey(byte[] value) { - if (value.Length > 32) + if (value.Length > LENGTH) throw new ArgumentOutOfRangeException(nameof(value)); _value = value; From 6d2d40320ae9eb2abf7a5e67251cd25c10e91498 Mon Sep 17 00:00:00 2001 From: TheDude Date: Wed, 12 Jan 2022 11:16:16 +0000 Subject: [PATCH 10/13] Opened channel successfully with LND --- .../Entities/ChannelCandidate.cs | 3 ++ .../FundingLockedMessageService.cs | 28 ++++++++++++++++++- .../Messages/OpenChannel.cs | 2 -- .../Bolt2/Entities/PaymentChannel.cs | 9 ++++-- 4 files changed, 36 insertions(+), 6 deletions(-) diff --git a/src/Lyn.Protocol/Bolt2/ChannelEstablishment/Entities/ChannelCandidate.cs b/src/Lyn.Protocol/Bolt2/ChannelEstablishment/Entities/ChannelCandidate.cs index ed6abea..f491905 100644 --- a/src/Lyn.Protocol/Bolt2/ChannelEstablishment/Entities/ChannelCandidate.cs +++ b/src/Lyn.Protocol/Bolt2/ChannelEstablishment/Entities/ChannelCandidate.cs @@ -1,6 +1,7 @@ using Lyn.Protocol.Bolt2.ChannelEstablishment.Messages; using Lyn.Protocol.Bolt3.Types; using Lyn.Types.Bitcoin; +using Lyn.Types.Bolt; namespace Lyn.Protocol.Bolt2.ChannelEstablishment.Entities { @@ -10,6 +11,8 @@ namespace Lyn.Protocol.Bolt2.ChannelEstablishment.Entities public class ChannelCandidate { public UInt256? ChannelId { get; set; } + + public ShortChannelId? ShortChannelId { get; set; } public ChannelSide ChannelOpener { get; set; } public OpenChannel? OpenChannel { get; set; } public AcceptChannel? AcceptChannel { get; set; } diff --git a/src/Lyn.Protocol/Bolt2/ChannelEstablishment/FundingLockedMessageService.cs b/src/Lyn.Protocol/Bolt2/ChannelEstablishment/FundingLockedMessageService.cs index 6a59d9f..9255181 100644 --- a/src/Lyn.Protocol/Bolt2/ChannelEstablishment/FundingLockedMessageService.cs +++ b/src/Lyn.Protocol/Bolt2/ChannelEstablishment/FundingLockedMessageService.cs @@ -1,12 +1,18 @@ using System; using System.Threading.Tasks; +using Lyn.Protocol.Bolt1; using Lyn.Protocol.Bolt2.ChannelEstablishment.Messages; using Lyn.Protocol.Bolt2.Entities; using Lyn.Protocol.Bolt2.NormalOperations; using Lyn.Protocol.Bolt3; using Lyn.Protocol.Bolt3.Types; +using Lyn.Protocol.Bolt7; +using Lyn.Protocol.Bolt7.Entities; +using Lyn.Protocol.Bolt7.Messages; +using Lyn.Protocol.Bolt9; using Lyn.Protocol.Common.Messages; using Lyn.Protocol.Connection; +using Lyn.Types; using Lyn.Types.Bitcoin; using Microsoft.Extensions.Logging; @@ -17,18 +23,24 @@ public class FundingLockedMessageService : IBoltMessageService private readonly ILogger _logger; private readonly IChannelCandidateRepository _channelCandidateRepository; private readonly IPaymentChannelRepository _paymentChannelRepository; + private readonly IPeerRepository _peerRepository; private readonly ISecretStore _secretStore; private readonly ILightningKeyDerivation _lightningKeyDerivation; + private readonly IGossipRepository _gossipRepository; + private readonly IParseFeatureFlags _featureFlags; public FundingLockedMessageService(ILogger logger, IChannelCandidateRepository channelCandidateRepository, IPaymentChannelRepository paymentChannelRepository, - ISecretStore secretStore, ILightningKeyDerivation lightningKeyDerivation) + ISecretStore secretStore, ILightningKeyDerivation lightningKeyDerivation, IGossipRepository gossipRepository, IPeerRepository peerRepository, IParseFeatureFlags featureFlags) { _logger = logger; _channelCandidateRepository = channelCandidateRepository; _paymentChannelRepository = paymentChannelRepository; _secretStore = secretStore; _lightningKeyDerivation = lightningKeyDerivation; + _gossipRepository = gossipRepository; + _peerRepository = peerRepository; + _featureFlags = featureFlags; } public async Task ProcessMessageAsync(PeerMessage message) @@ -54,6 +66,9 @@ public async Task ProcessMessageAsync(PeerMessage ProcessMessageAsync(PeerMessage ProcessMessageAsync(PeerMessage(); } public UInt256 ChannelId { get; set; } From 94bbc0bccbaaf08d0e39d3376f6ef2b5190a3f8a Mon Sep 17 00:00:00 2001 From: TheDude Date: Wed, 12 Jan 2022 12:43:02 +0000 Subject: [PATCH 11/13] Added access to local node Id (without fixing tests) --- .../Bolt9/LynImplementedBoltFeaturesTests.cs | 2 +- .../FundingLockedMessageService.cs | 8 ++++++-- .../Common/DefaultIoCRegistrations.cs | 2 ++ src/Lyn.Protocol/Common/INodeSettings.cs | 17 +++++++++++++++++ 4 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 src/Lyn.Protocol/Common/INodeSettings.cs diff --git a/src/Lyn.Protocol.Tests/Bolt9/LynImplementedBoltFeaturesTests.cs b/src/Lyn.Protocol.Tests/Bolt9/LynImplementedBoltFeaturesTests.cs index b939438..49a4a0c 100644 --- a/src/Lyn.Protocol.Tests/Bolt9/LynImplementedBoltFeaturesTests.cs +++ b/src/Lyn.Protocol.Tests/Bolt9/LynImplementedBoltFeaturesTests.cs @@ -20,7 +20,7 @@ public void ReturnsAllFeaturesAsByteArray() { var featuresArray = _sut.GetSupportedFeatures(); - Assert.Equal(new byte[] {8, 32}, featuresArray); + Assert.Equal(new byte[] {8}, featuresArray); } [Fact] diff --git a/src/Lyn.Protocol/Bolt2/ChannelEstablishment/FundingLockedMessageService.cs b/src/Lyn.Protocol/Bolt2/ChannelEstablishment/FundingLockedMessageService.cs index 9255181..4b59f69 100644 --- a/src/Lyn.Protocol/Bolt2/ChannelEstablishment/FundingLockedMessageService.cs +++ b/src/Lyn.Protocol/Bolt2/ChannelEstablishment/FundingLockedMessageService.cs @@ -10,6 +10,7 @@ using Lyn.Protocol.Bolt7.Entities; using Lyn.Protocol.Bolt7.Messages; using Lyn.Protocol.Bolt9; +using Lyn.Protocol.Common; using Lyn.Protocol.Common.Messages; using Lyn.Protocol.Connection; using Lyn.Types; @@ -28,10 +29,12 @@ public class FundingLockedMessageService : IBoltMessageService private readonly ILightningKeyDerivation _lightningKeyDerivation; private readonly IGossipRepository _gossipRepository; private readonly IParseFeatureFlags _featureFlags; + private readonly INodeSettings _nodeSettings; public FundingLockedMessageService(ILogger logger, IChannelCandidateRepository channelCandidateRepository, IPaymentChannelRepository paymentChannelRepository, - ISecretStore secretStore, ILightningKeyDerivation lightningKeyDerivation, IGossipRepository gossipRepository, IPeerRepository peerRepository, IParseFeatureFlags featureFlags) + ISecretStore secretStore, ILightningKeyDerivation lightningKeyDerivation, IGossipRepository gossipRepository, + IPeerRepository peerRepository, IParseFeatureFlags featureFlags, INodeSettings nodeSettings) { _logger = logger; _channelCandidateRepository = channelCandidateRepository; @@ -41,6 +44,7 @@ public FundingLockedMessageService(ILogger logger, _gossipRepository = gossipRepository; _peerRepository = peerRepository; _featureFlags = featureFlags; + _nodeSettings = nodeSettings; } public async Task ProcessMessageAsync(PeerMessage message) @@ -119,7 +123,7 @@ await _gossipRepository.AddGossipChannelAsync(new GossipChannel(new ChannelAnnou NodeId1 = message.NodeId, BitcoinKey1 = channelCandidate.AcceptChannel.FundingPubkey, BitcoinKey2 = channelCandidate.OpenChannel.FundingPubkey, - NodeId2 = + NodeId2 = _nodeSettings.GetNodeId() })); var seed = _secretStore.GetSeed(); diff --git a/src/Lyn.Protocol/Common/DefaultIoCRegistrations.cs b/src/Lyn.Protocol/Common/DefaultIoCRegistrations.cs index 79c3009..6b9e83e 100644 --- a/src/Lyn.Protocol/Common/DefaultIoCRegistrations.cs +++ b/src/Lyn.Protocol/Common/DefaultIoCRegistrations.cs @@ -78,6 +78,8 @@ private static IServiceCollection AddDefaultComponents(this IServiceCollection s services.AddTransient(typeof(IBoltMessageSender<>), typeof(BoltMessageSender<>)); + services.AddSingleton(); + return services; } diff --git a/src/Lyn.Protocol/Common/INodeSettings.cs b/src/Lyn.Protocol/Common/INodeSettings.cs new file mode 100644 index 0000000..12aceaf --- /dev/null +++ b/src/Lyn.Protocol/Common/INodeSettings.cs @@ -0,0 +1,17 @@ +using Lyn.Types.Fundamental; + +namespace Lyn.Protocol.Common +{ + public interface INodeSettings + { + PublicKey GetNodeId(); + } + + class NodeSettings : INodeSettings + { + public PublicKey GetNodeId() + { + throw new System.NotImplementedException(); + } + } +} \ No newline at end of file From 8310e6d4e47b636871db583dbfa02056841dcab5 Mon Sep 17 00:00:00 2001 From: TheDude Date: Thu, 24 Feb 2022 13:59:26 +0000 Subject: [PATCH 12/13] Added lookup for transaction output index on transaction returned from wallet and fixed failing tests --- .../FullChannelEstablishmentTest.cs | 28 +++++++++++++++++-- .../Bolt3/Bolt3CommitmentTests.cs | 4 +-- .../Bolt3/Bolt3FundingTests.cs | 4 +-- .../Bolt3/Bolt3KeyDerivationTest.cs | 27 ++++++++++-------- .../AcceptChannelMessageService.cs | 22 +++++++++++++-- 5 files changed, 65 insertions(+), 20 deletions(-) diff --git a/src/Lyn.Protocol.Tests/Bolt2/ChannelEstablishment/FullChannelEstablishmentTest.cs b/src/Lyn.Protocol.Tests/Bolt2/ChannelEstablishment/FullChannelEstablishmentTest.cs index 2a8df4a..777a6d0 100644 --- a/src/Lyn.Protocol.Tests/Bolt2/ChannelEstablishment/FullChannelEstablishmentTest.cs +++ b/src/Lyn.Protocol.Tests/Bolt2/ChannelEstablishment/FullChannelEstablishmentTest.cs @@ -1,3 +1,4 @@ +using System; using System.Linq; using System.Threading.Tasks; using FluentAssertions; @@ -47,6 +48,8 @@ public class FullChannelEstablishmentTest private static UInt256 _chainHash = new(Hex.FromString("06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f")); + Mock walletLookup; + public FullChannelEstablishmentTest() { var loggerFactory = new LoggerFactory(); @@ -71,8 +74,8 @@ public FullChannelEstablishmentTest() new TransactionInputSerializer(new OutPointSerializer()), new TransactionOutputSerializer(), new TransactionWitnessSerializer(new TransactionWitnessComponentSerializer()))); - - var walletLookup = new Mock(); + + walletLookup = new Mock(); walletLookup.Setup(_ => _.IsAmountAvailableAsync(It.IsAny())) .ReturnsAsync(true); @@ -192,9 +195,30 @@ public FullChannelEstablishmentTest() "0x7dda8bb401b0236edb0e97de360626ba64c8eebffc1399ca4ce17831c196d8b3232c4eea5db33d60811c1f6d131b4f4cd9a330d0f50dcb063daaf648e40a9b30") }; + private void WithTheTransactionReturnedFromTheWallet() + { + var expectedTransaction = new Transaction + { + Outputs = new TransactionOutput[] + { + new() + { + PublicKeyScript = _lightningScripts.FundingWitnessScript(_expectedOpenChannel.FundingPubkey, + _acceptChannel.FundingPubkey), + Value = _expectedOpenChannel.FundingSatoshis + } + } + }; + + walletLookup.Setup(_ => _.GenerateTransactionForOutputAsync(It.IsAny())) + .Returns(Task.FromResult(expectedTransaction)); + } + [Fact] public async Task FullChannelEstablishmentScenarioCompletesSuccessfully() { + WithTheTransactionReturnedFromTheWallet(); + var openChannelResponse = await _openChannelService.CreateOpenChannelAsync(new CreateOpenChannelIn(_nodeId, _chainHash, 16000000, 0, 1000, false)); diff --git a/src/Lyn.Protocol.Tests/Bolt3/Bolt3CommitmentTests.cs b/src/Lyn.Protocol.Tests/Bolt3/Bolt3CommitmentTests.cs index e0eaf04..1ff779d 100644 --- a/src/Lyn.Protocol.Tests/Bolt3/Bolt3CommitmentTests.cs +++ b/src/Lyn.Protocol.Tests/Bolt3/Bolt3CommitmentTests.cs @@ -128,7 +128,7 @@ public void Bolt3CommitmentAndHtlcTransactionTest(Bolt3CommitmentTestVectors vec byte[] localTransactionBytes = Context.SerializationFactory.Serialize(localTransaction); - Assert.Equal(vectors.OutputCommitTx, Hex.ToString(localTransactionBytes.AsSpan()).Substring(2)); + Assert.Equal(vectors.OutputCommitTx, Hex.ToString(localTransactionBytes.AsSpan())); /* FIXME: naming here is kind of backwards: local revocation key * is derived from remote revocation basepoint, but it's local */ @@ -243,7 +243,7 @@ public void Bolt3CommitmentAndHtlcTransactionTest(Bolt3CommitmentTestVectors vec byte[] htlcTransactionBytes = Context.SerializationFactory.Serialize(htlcTransaction); - Assert.Equal(expectedHtlcHex, Hex.ToString(htlcTransactionBytes.AsSpan()).Substring(2)); + Assert.Equal(expectedHtlcHex, Hex.ToString(htlcTransactionBytes.AsSpan())); } } diff --git a/src/Lyn.Protocol.Tests/Bolt3/Bolt3FundingTests.cs b/src/Lyn.Protocol.Tests/Bolt3/Bolt3FundingTests.cs index 67a6bf9..e905854 100644 --- a/src/Lyn.Protocol.Tests/Bolt3/Bolt3FundingTests.cs +++ b/src/Lyn.Protocol.Tests/Bolt3/Bolt3FundingTests.cs @@ -88,7 +88,7 @@ public void AppendixBCreateFundingTransactionTest() } }; - var newtrxToSign = Transaction.Parse(Hex.ToString(serializationFactory.Serialize(newtrx)).Substring(2), NBitcoin.Network.RegTest); + var newtrxToSign = Transaction.Parse(Hex.ToString(serializationFactory.Serialize(newtrx)), NBitcoin.Network.RegTest); uint256? newtrxToSignHash = newtrxToSign.GetSignatureHash( block1.Transactions[0].Outputs[0].ScriptPubKey, @@ -104,7 +104,7 @@ public void AppendixBCreateFundingTransactionTest() Op.GetPushOp(block1Privkey.PubKey.ToBytes())) .ToBytes(); - Assert.Equal(trx.ToHex(), Hex.ToString(serializationFactory.Serialize(newtrx)).Substring(2)); + Assert.Equal(trx.ToHex(), Hex.ToString(serializationFactory.Serialize(newtrx))); // Check that the funding transaction scripts are equal. Assert.Equal(trx.Outputs[0].ScriptPubKey, scriptWit); diff --git a/src/Lyn.Protocol.Tests/Bolt3/Bolt3KeyDerivationTest.cs b/src/Lyn.Protocol.Tests/Bolt3/Bolt3KeyDerivationTest.cs index ba16d4a..cec7e1b 100644 --- a/src/Lyn.Protocol.Tests/Bolt3/Bolt3KeyDerivationTest.cs +++ b/src/Lyn.Protocol.Tests/Bolt3/Bolt3KeyDerivationTest.cs @@ -21,14 +21,14 @@ public void AppendixEKeyDerivationTest() PublicKey perCommitmentPoint = keyDerivation.PublicKeyFromPrivateKey(perCommitmentSecret); PublicKey basePoint = keyDerivation.PublicKeyFromPrivateKey(baseSecret); - Assert.Equal("0x025f7117a78150fe2ef97db7cfc83bd57b2e2c0d0dd25eaf467a4a1c2a45ce1486", Hex.ToString(perCommitmentPoint)); - Assert.Equal("0x036d6caac248af96f6afa7f904f550253a0f3ef3f5aa2fe6838a95b216691468e2", Hex.ToString(basePoint)); + Assert.Equal("0x025f7117a78150fe2ef97db7cfc83bd57b2e2c0d0dd25eaf467a4a1c2a45ce1486", GetHexWithPrefix(perCommitmentPoint)); + Assert.Equal("0x036d6caac248af96f6afa7f904f550253a0f3ef3f5aa2fe6838a95b216691468e2", GetHexWithPrefix(basePoint)); PublicKey pubkey = keyDerivation.DerivePublickey(basePoint, perCommitmentPoint); PrivateKey privkey = keyDerivation.DerivePrivatekey(baseSecret, basePoint, perCommitmentPoint); - Assert.Equal("0x0235f2dbfaa89b57ec7b055afe29849ef7ddfeb1cefdb9ebdc43f5494984db29e5", Hex.ToString(pubkey)); - Assert.Equal("0xcbced912d3b21bf196a766651e436aff192362621ce317704ea2f75d87e7be0f", Hex.ToString(privkey)); + Assert.Equal("0x0235f2dbfaa89b57ec7b055afe29849ef7ddfeb1cefdb9ebdc43f5494984db29e5", GetHexWithPrefix(pubkey)); + Assert.Equal("0xcbced912d3b21bf196a766651e436aff192362621ce317704ea2f75d87e7be0f", GetHexWithPrefix(privkey)); PublicKey pubkey2 = keyDerivation.PublicKeyFromPrivateKey(privkey); Assert.Equal(pubkey.GetSpan().ToArray(), pubkey2.GetSpan().ToArray()); @@ -36,8 +36,8 @@ public void AppendixEKeyDerivationTest() pubkey = keyDerivation.DeriveRevocationPublicKey(basePoint, perCommitmentPoint); privkey = keyDerivation.DeriveRevocationPrivatekey(basePoint, baseSecret, perCommitmentSecret, perCommitmentPoint); - Assert.Equal("0x02916e326636d19c33f13e8c0c3a03dd157f332f3e99c317c141dd865eb01f8ff0", Hex.ToString(pubkey)); - Assert.Equal("0xd09ffff62ddb2297ab000cc85bcb4283fdeb6aa052affbc9dddcf33b61078110", Hex.ToString(privkey)); + Assert.Equal("0x02916e326636d19c33f13e8c0c3a03dd157f332f3e99c317c141dd865eb01f8ff0", GetHexWithPrefix(pubkey)); + Assert.Equal("0xd09ffff62ddb2297ab000cc85bcb4283fdeb6aa052affbc9dddcf33b61078110", GetHexWithPrefix(privkey)); pubkey2 = keyDerivation.PublicKeyFromPrivateKey(privkey); Assert.Equal(pubkey.GetSpan().ToArray(), pubkey2.GetSpan().ToArray()); @@ -88,31 +88,36 @@ public void PercommitmentSecretGenerationTest() UInt256 seed = new UInt256(Hex.FromString("0x0000000000000000000000000000000000000000000000000000000000000000")); ulong index = 281474976710655; Secret output = keyDerivation.PerCommitmentSecret(seed, index); - Assert.Equal("0x02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148", Hex.ToString(output)); + Assert.Equal("0x02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148", GetHexWithPrefix(output)); // generate_from_seed FF final node seed = new UInt256(Hex.FromString("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")); index = 281474976710655; output = keyDerivation.PerCommitmentSecret(seed, index); - Assert.Equal("0x7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc", Hex.ToString(output)); + Assert.Equal("0x7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc", GetHexWithPrefix(output)); // genegenerate_from_seed FF alternate bits 1 seed = new UInt256(Hex.FromString("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")); index = 0xaaaaaaaaaaa; output = keyDerivation.PerCommitmentSecret(seed, index); - Assert.Equal("0x56f4008fb007ca9acf0e15b054d5c9fd12ee06cea347914ddbaed70d1c13a528", Hex.ToString(output)); + Assert.Equal("0x56f4008fb007ca9acf0e15b054d5c9fd12ee06cea347914ddbaed70d1c13a528", GetHexWithPrefix(output)); // generate_from_seed FF alternate bits 2 seed = new UInt256(Hex.FromString("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")); index = 0x555555555555; output = keyDerivation.PerCommitmentSecret(seed, index); - Assert.Equal("0x9015daaeb06dba4ccc05b91b2f73bd54405f2be9f217fbacd3c5ac2e62327d31", Hex.ToString(output)); + Assert.Equal("0x9015daaeb06dba4ccc05b91b2f73bd54405f2be9f217fbacd3c5ac2e62327d31", GetHexWithPrefix(output)); // generate_from_seed 01 last nontrivial node seed = new UInt256(Hex.FromString("0x0101010101010101010101010101010101010101010101010101010101010101")); index = 1; output = keyDerivation.PerCommitmentSecret(seed, index); - Assert.Equal("0x915c75942a26bb3a433a8ce2cb0427c29ec6c1775cfc78328b57f6ba7bfeaa9c", Hex.ToString(output)); + Assert.Equal("0x915c75942a26bb3a433a8ce2cb0427c29ec6c1775cfc78328b57f6ba7bfeaa9c", GetHexWithPrefix(output)); + } + + private string GetHexWithPrefix(byte[] arr) + { + return "0x" + Hex.ToString(arr); } } } \ No newline at end of file diff --git a/src/Lyn.Protocol/Bolt2/ChannelEstablishment/AcceptChannelMessageService.cs b/src/Lyn.Protocol/Bolt2/ChannelEstablishment/AcceptChannelMessageService.cs index 18f7f03..31c515c 100644 --- a/src/Lyn.Protocol/Bolt2/ChannelEstablishment/AcceptChannelMessageService.cs +++ b/src/Lyn.Protocol/Bolt2/ChannelEstablishment/AcceptChannelMessageService.cs @@ -1,4 +1,6 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.Linq; using Lyn.Protocol.Bolt2.ChannelEstablishment.Entities; using Lyn.Protocol.Bolt2.ChannelEstablishment.Messages; using Lyn.Protocol.Bolt3; @@ -124,9 +126,9 @@ public async Task ProcessMessageAsync(PeerMessage ProcessMessageAsync(PeerMessage Date: Thu, 24 Feb 2022 14:01:31 +0000 Subject: [PATCH 13/13] Changed docker files in folder to LF --- docker/test-network/eclair/Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/docker/test-network/eclair/Dockerfile b/docker/test-network/eclair/Dockerfile index c7f6c47..c39b172 100644 --- a/docker/test-network/eclair/Dockerfile +++ b/docker/test-network/eclair/Dockerfile @@ -31,6 +31,7 @@ ADD wait-for-bitcoind.sh /usr/local/bin RUN chmod +x /usr/local/bin/wait-for-bitcoind.sh EXPOSE 9735 +EXPOSE 8080 ENTRYPOINT ["/usr/local/bin/eclair-entrypoint.sh"] # Show logs from beginning and keep following