< 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: 44_19672976073
Line coverage
92%
Covered lines: 52
Uncovered lines: 4
Coverable lines: 56
Total lines: 133
Line coverage: 92.8%
Branch coverage
81%
Covered branches: 18
Total branches: 22
Branch coverage: 81.8%
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(...)90%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{
 31622    public TaggedFieldTypes Type => TaggedFieldTypes.RoutingInfo;
 25223    internal RoutingInfoCollection Value { get; }
 6824    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>
 2430    internal RoutingInfoTaggedField(RoutingInfoCollection value)
 31    {
 2432        Value = value;
 2433        Length = (short)((value.Count * TaggedFieldConstants.RoutingInfoLength + value.Count * 2) / 5);
 34
 2435        Value.Changed += OnRoutingInfoCollectionChanged;
 2436    }
 37
 38    /// <inheritdoc/>
 39    public void WriteToBitWriter(BitWriter bitWriter)
 40    {
 41        // Write data
 9642        foreach (var routingInfo in Value)
 43        {
 2844            bitWriter.WriteBits(routingInfo.CompactPubKey, 264);
 2845            bitWriter.WriteBits(routingInfo.ShortChannelId, 64);
 2846            bitWriter.WriteInt32AsBits(routingInfo.FeeBaseMsat, 32);
 2847            bitWriter.WriteInt32AsBits(routingInfo.FeeProportionalMillionths, 32);
 2848            bitWriter.WriteInt16AsBits(routingInfo.CltvExpiryDelta, 16);
 49        }
 50
 15251        for (var i = 0; i < Value.Count * 2; i++)
 5652            bitWriter.WriteBit(false);
 2053    }
 54
 55    /// <inheritdoc/>
 56    public bool IsValid()
 57    {
 11258        foreach (var routingInfo in Value)
 59        {
 3260            if (routingInfo.FeeBaseMsat < 0)
 061                return false;
 62
 3263            if (routingInfo.FeeProportionalMillionths < 0)
 064                return false;
 65
 3266            if (routingInfo.CltvExpiryDelta < 0)
 067                return false;
 68        }
 69
 2470        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    {
 884        var l = length * 5;
 885        var bitsReadAcc = 0;
 886        var routingInfos = new RoutingInfoCollection();
 87
 88        // Check if there's enough data for the r field
 889        if (l >= TaggedFieldConstants.RoutingInfoLength)
 90        {
 891            for (var i = 0;
 2092                 i < l && l - bitsReadAcc >= TaggedFieldConstants.RoutingInfoLength;
 1293                 i += TaggedFieldConstants.RoutingInfoLength)
 94            {
 1295                var pubkeyBytes = new byte[34];
 1296                bitsReadAcc += bitReader.ReadBits(pubkeyBytes, 264);
 97
 1298                var shortChannelBytes = new byte[9];
 1299                bitsReadAcc += bitReader.ReadBits(shortChannelBytes, 64);
 100
 12101                var feeBaseMsat = bitReader.ReadInt32FromBits(32);
 12102                bitsReadAcc += 32;
 103
 12104                var feeProportionalMillionths = bitReader.ReadInt32FromBits(32);
 12105                bitsReadAcc += 32;
 106
 12107                var minFinalCltvExpiry = bitReader.ReadInt16FromBits(16);
 12108                bitsReadAcc += 16;
 109
 12110                routingInfos.Add(new RoutingInfo(new CompactPubKey(pubkeyBytes[..^1]),
 12111                                                 new ShortChannelId(shortChannelBytes[..^1]),
 12112                                                 feeBaseMsat,
 12113                                                 feeProportionalMillionths,
 12114                                                 minFinalCltvExpiry));
 115            }
 116        }
 117
 118        // Skip any extra bits since padding is expected
 8119        var extraBitsToSkip = l - bitsReadAcc;
 8120        if (extraBitsToSkip > 0)
 8121            bitReader.SkipBits(extraBitsToSkip);
 122
 123        // Return null if there's no routing info present
 8124        return routingInfos.Count > 0
 8125                   ? new RoutingInfoTaggedField(routingInfos)
 8126                   : 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}