Skip to content

Implement Lightning protocol support for BOLT 2, 4, 7, 9, 10 and 11 - #31

Open
sondreb wants to merge 1 commit into
masterfrom
lightning-protocol-completion
Open

Implement Lightning protocol support for BOLT 2, 4, 7, 9, 10 and 11#31
sondreb wants to merge 1 commit into
masterfrom
lightning-protocol-completion

Conversation

@sondreb

@sondreb sondreb commented Aug 23, 2026

Copy link
Copy Markdown
Member

Summary

Completes the Lightning Network protocol implementation in Lyn. The test suite grows from 122 to 166 passing tests.

BOLT Before After
BOLT 1: Base Protocol done done
BOLT 2: Peer Protocol for Channel Management partial complete
BOLT 3: Bitcoin Transaction and Script Formats done done
BOLT 4: Onion Routing Protocol missing implemented
BOLT 7: P2P Node and Channel Discovery partial complete (gossip queries)
BOLT 8: Encrypted and Authenticated Transport done done
BOLT 9: Assigned Feature Flags partial all assigned features
BOLT 10: DNS Bootstrap missing implemented
BOLT 11: Invoice Protocol missing implemented

Changes

BOLT 4 - Onion Routing (new)

  • Sphinx packet construction in reverse route order with per-hop filler generation, shared secret derivation and ephemeral key blinding
  • Packet processing with constant-time HMAC verification, layer peeling and forward packet blinding
  • Variable length (var_onion_optin) TLV hop payloads: amt_to_forward, outgoing_cltv_value, short_channel_id, payment_data (payment secret + total msat), total_amount_msat, blinded route records
  • Encrypted error return path with um/ammag key derivations
  • Tests verify the official BOLT 4 test vectors byte-for-byte (shared secrets, um/ammag keys) plus multi-hop round trips

BOLT 11 - Invoice Protocol (new)

  • Bech32 codec without the 90 character limit
  • Invoice parser/verifier: public key recovery, low-S enforcement when n is present, amount multipliers (m/u/n/p), payment hash/secret, description/description-hash exclusivity, expiry, min final CLTV, fallback addresses, route hints, feature bits, payment metadata
  • Invoice builder/signer producing spec compliant invoices
  • Tests parse the official test vectors and the builder reproduces an official signed invoice byte-for-byte

BOLT 2 - Channel management completed

  • Wire serializers and processing services for normal operations: update_add_htlc, update_fulfill_htlc, update_fail_htlc, update_fail_malformed_htlc, update_fee, commitment_signed (replies with revoke_and_ack), revoke_and_ack
  • Cooperative close: shutdown (script type validation, wallet destination) and closing_signed (fee negotiation)
  • HTLC bookkeeping on PaymentChannel, fixed message shapes to match the spec (UpdateFailHtlc.Id, CommitmentSigned.HtlcSignature, Shutdown.Length)

BOLT 7 - Gossip queries completed

  • Messages, serializers and services for query_channel_range, reply_channel_range, query_short_channel_ids, reply_short_channel_ids_end
  • BOLT 7 encoded short channel id format (uncompressed + zlib)

BOLT 9 - Feature flags updated

  • Feature enum extended to all currently assigned features through bit 63
  • Node advertises gossip_queries, var_onion_optin, option_static_remotekey, payment_secret, option_upfront_shutdown_script, basic_mpp

BOLT 10 - DNS bootstrap (new)

  • Minimal UDP DNS client supporting A, AAAA and SRV records with name compression
  • DNS seed client encoding query conditions and decoding bech32 virtual hostnames into node ids

Fixes and infrastructure

  • Value equality (IEquatable) for ShortChannelId, MiliSatoshis, Satoshis, PrivateKey; fixes latent gossip repository lookups
  • HashGenerator.Sha256AsUInt256 helper
  • Retarget solution from net5.0 to net10.0 so the suite runs on current .NET SDKs

BOLT 5 (on-chain transaction handling) remains out of scope pending real wallet integration.

- BOLT 4: sphinx onion packet construction, processing, key blinding,
  variable length TLV hop payloads and the encrypted error return path,
  verified against the official test vectors
- BOLT 11: bech32 codec plus invoice parsing/creation with payment
  secrets, feature bits, fallback addresses, route hints and public key
  recovery, verified against the official test vectors
- BOLT 2: wire serializers and processing services for normal operations
  (update_add_htlc, update_fulfill_htlc, update_fail_htlc,
  update_fail_malformed_htlc, update_fee, commitment_signed,
  revoke_and_ack) and cooperative close (shutdown, closing_signed)
- BOLT 7: gossip query messages (query_channel_range,
  reply_channel_range, query_short_channel_ids,
  reply_short_channel_ids_end) with encoded short channel id support
- BOLT 9: feature flag enum updated to all currently assigned features,
  node now advertises gossip_queries, var_onion_optin,
  option_static_remotekey, payment_secret, option_upfront_shutdown_script
  and basic_mpp
- BOLT 10: minimal UDP DNS client (A/AAAA/SRV) and DNS seed client that
  decodes bech32 virtual hostnames into node ids
- Fix value equality for ShortChannelId, MiliSatoshis, Satoshis and
  PrivateKey; retarget solution to net10.0

Test suite grows from 122 to 166 tests, all passing.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Expands Lyn’s Lightning protocol coverage across channel management, onion routing, gossip, feature flags, DNS bootstrap, and invoices.

Changes:

  • Adds BOLT 2, 4, 7, 10, and 11 implementations.
  • Extends feature flags, value equality, serialization, and repositories.
  • Adds protocol tests and targets .NET 10.

Reviewed changes

Copilot reviewed 74 out of 74 changed files in this pull request and generated 34 comments.

Show a summary per file
File Description
README.md Updates protocol status.
src/Directory.Build.props Targets .NET 10.
src/Lyn.Types/Fundamental/Satoshis.cs Adds value equality.
src/Lyn.Types/Fundamental/MiliSatoshis.cs Adds value equality.
src/Lyn.Types/Fundamental/PrivateKey.cs Adds key equality.
src/Lyn.Types/Bolt/ShortChannelId.cs Adds conversion and equality.
src/Lyn.Protocol/Common/Messages/MessageType.cs Adds message types.
src/Lyn.Protocol/Common/Hashing/HashGenerator.cs Adds SHA-256 helper.
src/Lyn.Protocol/Common/DefaultIoCRegistrations.cs Registers new services.
src/Lyn.Protocol/Bolt1/Messages/Features.cs Extends feature flags.
src/Lyn.Protocol/Bolt2/Entities/PaymentChannel.cs Adds close and HTLC state.
src/Lyn.Protocol/Bolt2/NormalOperations/IPaymentChannelRepository.cs Adds channel updates.
src/Lyn.Protocol/Bolt2/NormalOperations/InMemoryPaymentChannelRepository.cs Implements updates.
src/Lyn.Protocol/Bolt2/NormalOperations/UpdateAddHtlcMessageService.cs Processes added HTLCs.
src/Lyn.Protocol/Bolt2/NormalOperations/UpdateFulfillHtlcMessageService.cs Processes fulfillment.
src/Lyn.Protocol/Bolt2/NormalOperations/UpdateFailHtlcMessageService.cs Processes failures.
src/Lyn.Protocol/Bolt2/NormalOperations/UpdateFailMalformedHtlcMessageService.cs Processes malformed onions.
src/Lyn.Protocol/Bolt2/NormalOperations/UpdateFeeMessageService.cs Processes fee updates.
src/Lyn.Protocol/Bolt2/NormalOperations/CommitmentSignedMessageService.cs Handles commitments.
src/Lyn.Protocol/Bolt2/NormalOperations/RevokeAndAckMessageService.cs Handles revocations.
src/Lyn.Protocol/Bolt2/NormalOperations/Messages/UpdateAddHtlcSerializer.cs Serializes added HTLCs.
src/Lyn.Protocol/Bolt2/NormalOperations/Messages/UpdateFulfillHtlcSerializer.cs Serializes fulfillments.
src/Lyn.Protocol/Bolt2/NormalOperations/Messages/UpdateFailHtlcSerializer.cs Serializes failures.
src/Lyn.Protocol/Bolt2/NormalOperations/Messages/UpdateFailMalformedHtlcSerializer.cs Serializes malformed failures.
src/Lyn.Protocol/Bolt2/NormalOperations/Messages/UpdateFeeSerializer.cs Serializes fee updates.
src/Lyn.Protocol/Bolt2/NormalOperations/Messages/RevokeAndAckSerializer.cs Serializes revocations.
src/Lyn.Protocol/Bolt2/NormalOperations/Messages/CommitmentSignedSerializer.cs Serializes commitments.
src/Lyn.Protocol/Bolt2/NormalOperations/Messages/CommitmentSigned.cs Corrects HTLC signatures.
src/Lyn.Protocol/Bolt2/NormalOperations/Messages/UpdateFailHtlc.cs Adds HTLC ID.
src/Lyn.Protocol/Bolt2/ChannelClose/ShutdownMessageService.cs Handles shutdown.
src/Lyn.Protocol/Bolt2/ChannelClose/ClosingSignedMessageService.cs Negotiates closing fees.
src/Lyn.Protocol/Bolt2/ChannelClose/Messages/ShutdownSerializer.cs Serializes shutdowns.
src/Lyn.Protocol/Bolt2/ChannelClose/Messages/Shutdown.cs Corrects length field.
src/Lyn.Protocol/Bolt2/ChannelClose/Messages/ClosingSignedSerializer.cs Serializes closing signatures.
src/Lyn.Protocol/Bolt2/MessageRetransmission/Messages/ChannelReestablish.cs Adds default construction.
src/Lyn.Protocol/Bolt4/SphinxSharedSecrets.cs Derives Sphinx secrets.
src/Lyn.Protocol/Bolt4/SphinxKeys.cs Derives onion keys.
src/Lyn.Protocol/Bolt4/OnionPacket.cs Models onion packets.
src/Lyn.Protocol/Bolt4/OnionPacketBuilder.cs Builds onion packets.
src/Lyn.Protocol/Bolt4/OnionPacketProcessor.cs Peels onion layers.
src/Lyn.Protocol/Bolt4/HopPayload.cs Encodes hop TLVs.
src/Lyn.Protocol/Bolt4/FailureObfuscator.cs Implements error return paths.
src/Lyn.Protocol/Bolt7/IGossipRepository.cs Adds channel enumeration.
src/Lyn.Protocol/Bolt7/InMemoryGossipRepository.cs Implements enumeration.
src/Lyn.Protocol/Bolt7/EncodedShortIds.cs Encodes gossip IDs.
src/Lyn.Protocol/Bolt7/QueryChannelRangeService.cs Answers range queries.
src/Lyn.Protocol/Bolt7/QueryShortChannelIdsService.cs Answers ID queries.
src/Lyn.Protocol/Bolt7/ReplyChannelRangeService.cs Processes range replies.
src/Lyn.Protocol/Bolt7/ReplyShortChannelIdsEndService.cs Completes gossip queries.
src/Lyn.Protocol/Bolt7/Messages/QueryChannelRange.cs Models range queries.
src/Lyn.Protocol/Bolt7/Messages/QueryChannelRangeSerializer.cs Serializes range queries.
src/Lyn.Protocol/Bolt7/Messages/QueryShortChannelIdsSerializer.cs Serializes ID queries.
src/Lyn.Protocol/Bolt7/Messages/ReplyChannelRange.cs Models range replies.
src/Lyn.Protocol/Bolt7/Messages/ReplyChannelRangeSerializer.cs Serializes range replies.
src/Lyn.Protocol/Bolt7/Messages/ReplyShortChannelIdsEnd.cs Models query completion.
src/Lyn.Protocol/Bolt7/Messages/ReplyShortChannelIdsEndSerializer.cs Serializes query completion.
src/Lyn.Protocol/Bolt9/LynImplementedBoltFeatures.cs Advertises implemented features.
src/Lyn.Protocol/Bolt10/UdpDnsResolver.cs Implements UDP DNS.
src/Lyn.Protocol/Bolt10/DnsSeedClient.cs Discovers seed nodes.
src/Lyn.Protocol/Bolt11/Bech32.cs Implements Bech32.
src/Lyn.Protocol/Bolt11/Bolt11Invoice.cs Models invoices.
src/Lyn.Protocol/Bolt11/Bolt11InvoiceParser.cs Parses invoices.
src/Lyn.Protocol/Bolt11/Bolt11InvoiceBuilder.cs Builds signed invoices.
src/Lyn.Protocol.Tests/Lyn.Protocol.Tests.csproj Targets .NET 10.
src/Lyn.Protocol.Tests/Bolt2/Bolt2MessageSerializationTests.cs Tests BOLT 2 serialization.
src/Lyn.Protocol.Tests/Bolt2/Bolt2ChannelCloseAndCommitmentTests.cs Tests channel operations.
src/Lyn.Protocol.Tests/Bolt2/ChannelEstablishment/FullChannelEstablishmentTest.cs Updates channel fixtures.
src/Lyn.Protocol.Tests/Bolt3/Bolt3CommitmentTests.cs Updates hash conversions.
src/Lyn.Protocol.Tests/Bolt4/SphinxTests.cs Tests onion routing.
src/Lyn.Protocol.Tests/Bolt7/Bolt7GossipQueryTests.cs Tests gossip queries.
src/Lyn.Protocol.Tests/Bolt9/LynImplementedBoltFeaturesTests.cs Tests advertised features.
src/Lyn.Protocol.Tests/Bolt10/Bolt10Tests.cs Tests DNS bootstrap.
src/Lyn.Protocol.Tests/Bolt11/Bolt11TestVectors.cs Adds invoice vectors.
src/Lyn.Protocol.Tests/Bolt11/Bolt11Tests.cs Tests invoice handling.
Suppressed comments (5)

src/Lyn.Protocol/Bolt7/Messages/QueryShortChannelIdsSerializer.cs:22

  • This writes chain_hash in the opposite byte order from existing BOLT 7 messages, so peers receive the display-order genesis hash rather than the protocol wire value.
    src/Lyn.Protocol/Bolt7/Messages/QueryChannelRangeSerializer.cs:23
  • Serialize this chain_hash with the same reversed wire representation as the other BOLT 7 messages; the current value is byte-swapped on the network.
    src/Lyn.Protocol/Bolt7/Messages/ReplyChannelRangeSerializer.cs:29
  • The reply must write chain_hash using the BOLT 7 reversed hash wire representation, consistent with ChannelAnnouncementSerializer.
    src/Lyn.Protocol/Bolt7/Messages/ReplyShortChannelIdsEndSerializer.cs:22
  • Write this chain_hash with byte reversal, as done by existing BOLT 7 serializers; otherwise the end marker refers to the wrong chain on the wire.
    src/Lyn.Protocol/Bolt2/NormalOperations/Messages/CommitmentSignedSerializer.cs:39
  • Serialization repeats the same field-order inversion: num_htlcs is emitted before the mandatory signature. Peers will parse these bytes as the start of the signature, making every outbound commitment invalid.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +44 to +50
public override int GetHashCode()
{
if (_value.Length == 0)
return 0;

return _value[0] | (_value[1] << 8) | (_value[2] << 16) | (_value[3] << 24);
}
/// </summary>
public ulong ToUInt64()
{
return ((ulong)(uint)BlockHeight << 40) | ((ulong)(uint)TransactionIndex << 16) | OutputIndex;
Comment on lines +27 to +28
foreach (ShortChannelId shortChannelId in shortChannelIds)
WriteBigSize(stream, shortChannelId.ToUInt64());
continue;
}

responses.Add(new BoltMessage { Payload = channel.ChannelAnnouncement });
Comment on lines +38 to +40
if (channel is null)
{
complete = false;
Comment on lines +56 to +59
OptionSimpleCloseRequired = 1UL << 60,
OptionSimpleClose = 1UL << 61,
OptionSpliceRequired = 1UL << 62,
OptionSplice = 1UL << 63,
| Features.OptionStaticRemotekey
| Features.PaymentSecret
| Features.OptionUpfrontShutdownScript
| Features.BasicMpp;
Comment thread README.md
- [X] BOLT 2: Peer Protocol for Channel Management
- [X] BOLT 3: Bitcoin Transaction and Script Formats
- [ ] BOLT 4: Onion Routing Protocol
- [X] BOLT 4: Onion Routing Protocol (sphinx packet construction, processing and error return path)
if (separator <= 0)
continue;

string hostname = record.Name.Substring(0, separator);
Comment on lines +48 to +60
case ENCODING_ZLIB_DEFLATE:
using (var compressedStream = new MemoryStream(encoded, 1, encoded.Length - 1))
using (var decompressedStream = new MemoryStream())
{
using (var deflateStream = new DeflateStream(compressedStream, CompressionMode.Decompress))
{
deflateStream.CopyTo(decompressedStream);
}

payload = decompressedStream.ToArray().AsSpan();
}

break;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants