private void OnClosingSigned(IPeer peer, ClosingSignedMessage message) { var channel = _channelService.Channels.SingleOrDefault(c => c.ChannelId == message.ChannelId.ToHex()); if (channel == null) { _logger.LogDebug($"Remote sent us a {nameof(ClosingSignedMessage)}, but there is no matching channel."); peer.Messaging.Send(ErrorMessage.UnknownChannel(message.ChannelId)); return; } // TODO: verify signature var signedCloseTx = BuildSignedCloseTransaction(channel, SignatureConverter.RawToTransactionSignature(message.Signature), message.FeeSatoshi); if (channel.IsFunder) { bool isFairFee = IsFairFee(signedCloseTx, message.FeeSatoshi); if (isFairFee) { _channelLoggingService.LogInfo(channel, "Mutual Close Transaction", signedCloseTx.ToString()); _blockchainClientService.SendTransaction(signedCloseTx); } else if (_failedFeeNegotiations.Contains(channel)) { _logger.LogWarning("Unable to negotiate a fair fee for our closing transaction. Will do a unilateral close."); UnilateralClose(channel); } else { _failedFeeNegotiations.Add(channel); RespondWithClosingSigned(peer, channel); } } else { RespondWithClosingSigned(peer, channel, message.FeeSatoshi); } _channelService.UpdateChannel(channel); }
private void RespondWithClosingSigned(IPeer peer, LocalChannel channel, ulong fee = 0) { var oldState = channel.State; ulong ourFeeRate = _blockchainClientService.GetFeeRatePerKw(3); channel.State = LocalChannelState.ClosingSigned; var builder = new CloseChannelTransactionBuilder(channel, _networkParameters); builder.FeeSatoshi = 0; var zeroFeeTx = builder.Build(); builder.FeeSatoshi = fee != 0 ? fee : TransactionFee.CalculateFee(ourFeeRate, (ulong)zeroFeeTx.GetSerializedSize(2, SerializationType.Network)); ClosingSignedMessage closingSignedMessage = new ClosingSignedMessage(); closingSignedMessage.FeeSatoshi = builder.FeeSatoshi; closingSignedMessage.ChannelId = channel.ChannelId.HexToByteArray(); closingSignedMessage.Signature = builder.Sign().ToRawSignature(); peer.Messaging.Send(closingSignedMessage); _channelLoggingService.LogStateUpdate(channel, oldState, "Respond with closing signed"); }