< Summary - Combined Code Coverage

Information
Class: NLightning.Bolt11.Models.TaggedFields.RoutingInfoTaggedField
Assembly: NLightning.Bolt11
File(s): /home/runner/work/nlightning/nlightning/src/NLightning.Bolt11/Models/TaggedFields/RoutingInfoTaggedField.cs
Tag: 49_19945309242
Line coverage
92%
Covered lines: 52
Uncovered lines: 4
Coverable lines: 56
Total lines: 133
Line coverage: 92.8%
Branch coverage
86%
Covered branches: 19
Total branches: 22
Branch coverage: 86.3%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
get_Type()100%11100%
get_Value()100%11100%
get_Length()100%11100%
.ctor(...)100%11100%
WriteToBitWriter(...)100%44100%
IsValid()62.5%13.62855.56%
FromBitReader(...)100%1010100%
OnRoutingInfoCollectionChanged(...)100%11100%

File(s)

/home/runner/work/nlightning/nlightning/src/NLightning.Bolt11/Models/TaggedFields/RoutingInfoTaggedField.cs

#LineLine coverage
 1namespace NLightning.Bolt11.Models.TaggedFields;
 2
 3using Constants;
 4using Domain.Channels.ValueObjects;
 5using Domain.Crypto.ValueObjects;
 6using Domain.Models;
 7using Domain.Utils;
 8using Enums;
 9using Interfaces;
 10
 11/// <summary>
 12/// Tagged field for routing information
 13/// </summary>
 14/// <remarks>
 15/// The routing information is a collection of routing information entries.
 16/// Each entry contains the public key of the node, the short channel id, the base fee in msat, the fee proportional
 17/// millionths, and the cltv expiry delta.
 18/// </remarks>
 19/// <seealso cref="ITaggedField"/>
 20internal sealed class RoutingInfoTaggedField : ITaggedField
 21{
 32022    public TaggedFieldTypes Type => TaggedFieldTypes.RoutingInfo;
 58823    internal RoutingInfoCollection Value { get; }
 22024    public short Length { get; private set; }
 25
 26    /// <summary>
 27    /// Initializes a new instance of the <see cref="DescriptionHashTaggedField"/> class.
 28    /// </summary>
 29    /// <param name="value">The Description Hash</param>
 10030    internal RoutingInfoTaggedField(RoutingInfoCollection value)
 31    {
 10032        Value = value;
 10033        Length = (short)((value.Count * TaggedFieldConstants.RoutingInfoLength + value.Count * 2) / 5);
 34
 10035        Value.Changed += OnRoutingInfoCollectionChanged;
 10036    }
 37
 38    /// <inheritdoc/>
 39    public void WriteToBitWriter(BitWriter bitWriter)
 40    {
 41        // Write data
 25642        foreach (var routingInfo in Value)
 43        {
 7244            bitWriter.WriteBits(routingInfo.CompactPubKey, 264);
 7245            bitWriter.WriteBits(routingInfo.ShortChannelId, 64);
 7246            bitWriter.WriteInt32AsBits(routingInfo.FeeBaseMsat, 32);
 7247            bitWriter.WriteInt32AsBits(routingInfo.FeeProportionalMillionths, 32);
 7248            bitWriter.WriteInt16AsBits(routingInfo.CltvExpiryDelta, 16);
 49        }
 50
 40051        for (var i = 0; i < Value.Count * 2; i++)
 14452            bitWriter.WriteBit(false);
 5653    }
 54
 55    /// <inheritdoc/>
 56    public bool IsValid()
 57    {
 12858        foreach (var routingInfo in Value)
 59        {
 3660            if (routingInfo.FeeBaseMsat < 0)
 061                return false;
 62
 3663            if (routingInfo.FeeProportionalMillionths < 0)
 064                return false;
 65
 3666            if (routingInfo.CltvExpiryDelta < 0)
 067                return false;
 68        }
 69
 2870        return true;
 071    }
 72
 73    /// <summary>
 74    /// Create a new instance of the <see cref="RoutingInfoTaggedField"/> from a <see cref="BitReader"/>
 75    /// </summary>
 76    /// <param name="bitReader">The bit reader to read from</param>
 77    /// <param name="length">The length of the tagged field</param>
 78    /// <returns>
 79    /// A new instance of the <see cref="RoutingInfoTaggedField"/> if routing information is present;
 80    /// otherwise, <c>null</c>.
 81    /// </returns>
 82    internal static RoutingInfoTaggedField? FromBitReader(BitReader bitReader, short length)
 83    {
 4884        var l = length * 5;
 4885        var bitsReadAcc = 0;
 4886        var routingInfos = new RoutingInfoCollection();
 87
 88        // Check if there's enough data for the r field
 4889        if (l >= TaggedFieldConstants.RoutingInfoLength)
 90        {
 4491            for (var i = 0;
 10092                 i < l && l - bitsReadAcc >= TaggedFieldConstants.RoutingInfoLength;
 5693                 i += TaggedFieldConstants.RoutingInfoLength)
 94            {
 5695                var pubkeyBytes = new byte[34];
 5696                bitsReadAcc += bitReader.ReadBits(pubkeyBytes, 264);
 97
 5698                var shortChannelBytes = new byte[9];
 5699                bitsReadAcc += bitReader.ReadBits(shortChannelBytes, 64);
 100
 56101                var feeBaseMsat = bitReader.ReadInt32FromBits(32);
 56102                bitsReadAcc += 32;
 103
 56104                var feeProportionalMillionths = bitReader.ReadInt32FromBits(32);
 56105                bitsReadAcc += 32;
 106
 56107                var minFinalCltvExpiry = bitReader.ReadInt16FromBits(16);
 56108                bitsReadAcc += 16;
 109
 56110                routingInfos.Add(new RoutingInfo(new CompactPubKey(pubkeyBytes[..^1]),
 56111                                                 new ShortChannelId(shortChannelBytes[..^1]),
 56112                                                 feeBaseMsat,
 56113                                                 feeProportionalMillionths,
 56114                                                 minFinalCltvExpiry));
 115            }
 116        }
 117
 118        // Skip any extra bits since padding is expected
 48119        var extraBitsToSkip = l - bitsReadAcc;
 48120        if (extraBitsToSkip > 0)
 48121            bitReader.SkipBits(extraBitsToSkip);
 122
 123        // Return null if there's no routing info present
 48124        return routingInfos.Count > 0
 48125                   ? new RoutingInfoTaggedField(routingInfos)
 48126                   : null;
 127    }
 128
 129    private void OnRoutingInfoCollectionChanged(object? sender, EventArgs e)
 130    {
 4131        Length = (short)((Value.Count * TaggedFieldConstants.RoutingInfoLength + Value.Count * 2) / 5);
 4132    }
 133}