< Summary - Combined Code Coverage

Information
Class: NLightning.Infrastructure.Transport.Encryption.Transport
Assembly: NLightning.Infrastructure
File(s): /home/runner/work/nlightning/nlightning/src/NLightning.Infrastructure/Transport/Encryption/Transport.cs
Tag: 36_15743069263
Line coverage
77%
Covered lines: 38
Uncovered lines: 11
Coverable lines: 49
Total lines: 168
Line coverage: 77.5%
Branch coverage
57%
Covered branches: 16
Total branches: 28
Branch coverage: 57.1%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
WriteMessage(...)100%22100%
ReadMessageLength(...)66.67%6.39677.78%
ReadMessagePayload(...)100%11100%
WriteMessagePart(...)50%13.62855.56%
ReadMessagePart(...)50%18.781055.56%
Dispose()50%2.02283.33%

File(s)

/home/runner/work/nlightning/nlightning/src/NLightning.Infrastructure/Transport/Encryption/Transport.cs

#LineLine coverage
 1namespace NLightning.Infrastructure.Transport.Encryption;
 2
 3using Domain.Crypto.Constants;
 4using Domain.Exceptions;
 5using Domain.Transport;
 6using Domain.Utils;
 7using Handshake.States;
 8using Protocol.Constants;
 9
 10/// <inheritdoc/>
 11internal sealed class Transport : ITransport
 12{
 13    private readonly bool _initiator;
 14    private readonly CipherState _sendingKey;
 15    private readonly CipherState _receivingKey;
 16
 17    private bool _disposed;
 18
 3219    public Transport(bool initiator, CipherState c1, CipherState c2)
 20    {
 3221        ArgumentNullException.ThrowIfNull(c1, nameof(c1));
 3222        ArgumentNullException.ThrowIfNull(c2, nameof(c2));
 23
 3224        _initiator = initiator;
 3225        _sendingKey = c1;
 3226        _receivingKey = c2;
 3227    }
 28
 29    /// <inheritdoc/>
 30    /// <exception cref="ObjectDisposedException">Thrown if the current instance has already been disposed.</exception>
 31    /// <exception cref="InvalidOperationException">Thrown if the responder has attempted to write a message to a one-wa
 32    /// <exception cref="ArgumentException">Thrown if the encrypted payload was greater than <see cref="ProtocolConstant
 33    public int WriteMessage(ReadOnlySpan<byte> payload, Span<byte> messageBuffer)
 34    {
 400835        ExceptionUtils.ThrowIfDisposed(_disposed, nameof(Transport));
 36
 37        // Serialize length into 2 bytes encoded as a big-endian integer
 400838        var l = BitConverter.GetBytes((ushort)payload.Length);
 400839        if (BitConverter.IsLittleEndian)
 40        {
 400841            Array.Reverse(l);
 42        }
 43
 44        // Encrypt the payload length into the message buffer
 400845        var lcLen = WriteMessagePart(l, messageBuffer);
 46
 47        // Encrypt the payload into the message buffer
 400848        var mLen = WriteMessagePart(payload, messageBuffer[lcLen..]);
 49
 400850        return lcLen + mLen;
 51    }
 52
 53    /// <inheritdoc/>
 54    public int ReadMessageLength(ReadOnlySpan<byte> lc)
 55    {
 400856        ExceptionUtils.ThrowIfDisposed(_disposed, nameof(Transport));
 57
 400858        if (lc.Length != ProtocolConstants.MessageHeaderSize)
 59        {
 060            throw new ArgumentException($"Lightning Message Header must be {ProtocolConstants.MessageHeaderSize} bytes i
 61        }
 62
 63        // Decrypt the payload length from the message buffer
 400864        var l = new byte[2];
 65        // Bytes read should always be 2
 400866        if (ReadMessagePart(lc, l) != 2)
 67        {
 068            throw new ConnectionException("Message Length was invalid.");
 69        }
 70
 400871        if (BitConverter.IsLittleEndian)
 72        {
 400873            Array.Reverse(l);
 74        }
 400875        return BitConverter.ToUInt16(l, 0) + CryptoConstants.Chacha20Poly1305TagLen;
 76    }
 77
 78    /// <inheritdoc/>
 79    public int ReadMessagePayload(ReadOnlySpan<byte> message, Span<byte> payloadBuffer)
 80    {
 400881        ExceptionUtils.ThrowIfDisposed(_disposed, nameof(Transport));
 82
 83        // Decrypt the payload from the message buffer
 400884        return ReadMessagePart(message, payloadBuffer);
 85    }
 86
 87    /// <summary>
 88    /// Encrypts the <paramref name="payload"/> and writes the result into <paramref name="messageBuffer"/>.
 89    /// </summary>
 90    /// <param name="payload">The payload to encrypt.</param>
 91    /// <param name="messageBuffer">The buffer for the encrypted message.</param>
 92    /// <returns>The ciphertext size in bytes.</returns>
 93    /// <exception cref="ObjectDisposedException">
 94    /// Thrown if the current instance has already been disposed.
 95    /// </exception>
 96    /// <exception cref="InvalidOperationException">
 97    /// Thrown if the responder has attempted to write a message to a one-way stream.
 98    /// </exception>
 99    /// <exception cref="ArgumentException">
 100    /// Thrown if the encrypted payload was greater than <see cref="ProtocolConstants.MaxMessageLength"/>
 101    /// bytes in length, or if the output buffer did not have enough space to hold the ciphertext.
 102    /// </exception>
 103    private int WriteMessagePart(ReadOnlySpan<byte> payload, Span<byte> messageBuffer)
 104    {
 8016105        if (payload.Length + CryptoConstants.Chacha20Poly1305TagLen > ProtocolConstants.MaxMessageLength)
 0106            throw new ArgumentException(
 0107                $"Noise message must be less than or equal to {ProtocolConstants.MaxMessageLength} bytes in length.");
 108
 8016109        if (payload.Length + CryptoConstants.Chacha20Poly1305TagLen > messageBuffer.Length)
 0110            throw new ArgumentException("Message buffer does not have enough space to hold the ciphertext.");
 111
 8016112        var cipher = _initiator ? _sendingKey : _receivingKey;
 8016113        if (!cipher.HasKeys())
 0114            throw new InvalidOperationException("Cipher is missing keys.");
 115
 8016116        return cipher.Encrypt(payload, messageBuffer);
 117    }
 118
 119    /// <summary>
 120    /// Decrypts the <paramref name="message"/> and writes the result into <paramref name="payloadBuffer"/>.
 121    /// </summary>
 122    /// <param name="message">The message to decrypt.</param>
 123    /// <param name="payloadBuffer">The buffer for the decrypted payload.</param>
 124    /// <returns>The plaintext size in bytes.</returns>
 125    /// <exception cref="ObjectDisposedException">
 126    /// Thrown if the current instance has already been disposed.
 127    /// </exception>
 128    /// <exception cref="InvalidOperationException">
 129    /// Thrown if the initiator has attempted to read a message from a one-way stream.
 130    /// </exception>
 131    /// <exception cref="ArgumentException">
 132    /// Thrown if the message was greater than <see cref="ProtocolConstants.MaxMessageLength"/>
 133    /// bytes in length, or if the output buffer did not have enough space to hold the plaintext.
 134    /// </exception>
 135    /// <exception cref="System.Security.Cryptography.CryptographicException">
 136    /// Thrown if the decryption of the message has failed.
 137    /// </exception>
 138    private int ReadMessagePart(ReadOnlySpan<byte> message, Span<byte> payloadBuffer)
 139    {
 8016140        switch (message.Length)
 141        {
 142            case > ProtocolConstants.MaxMessageLength:
 0143                throw new ArgumentException($"Noise message must be less than or equal to {ProtocolConstants.MaxMessageL
 144            case < CryptoConstants.Chacha20Poly1305TagLen:
 0145                throw new ArgumentException($"Noise message must be greater than or equal to {CryptoConstants.Chacha20Po
 146        }
 147
 8016148        if (message.Length - CryptoConstants.Chacha20Poly1305TagLen > payloadBuffer.Length)
 0149            throw new ArgumentException("Payload buffer does not have enough space to hold the plaintext.");
 150
 8016151        var cipher = _initiator ? _receivingKey : _sendingKey;
 8016152        if (!cipher.HasKeys())
 0153            throw new InvalidOperationException("Cipher is missing keys.");
 154
 8016155        return cipher.Decrypt(message, payloadBuffer);
 156    }
 157
 158    public void Dispose()
 159    {
 8160        if (_disposed)
 0161            return;
 162
 8163        _sendingKey.Dispose();
 8164        _receivingKey.Dispose();
 165
 8166        _disposed = true;
 8167    }
 168}