| | 1 | | namespace NLightning.Infrastructure.Bitcoin.Services; |
| | 2 | |
|
| | 3 | | using Domain.Bitcoin.Interfaces; |
| | 4 | | using Domain.Channels.ValueObjects; |
| | 5 | | using Domain.Crypto.ValueObjects; |
| | 6 | | using Domain.Protocol.Interfaces; |
| | 7 | |
|
| | 8 | | public class CommitmentKeyDerivationService : ICommitmentKeyDerivationService |
| | 9 | | { |
| | 10 | | private readonly IKeyDerivationService _keyDerivationService; |
| | 11 | | private readonly ILightningSigner _lightningSigner; |
| | 12 | |
|
| 0 | 13 | | public CommitmentKeyDerivationService(IKeyDerivationService keyDerivationService, ILightningSigner lightningSigner) |
| | 14 | | { |
| 0 | 15 | | _keyDerivationService = keyDerivationService; |
| 0 | 16 | | _lightningSigner = lightningSigner; |
| 0 | 17 | | } |
| | 18 | |
|
| | 19 | | /// <inheritdoc /> |
| | 20 | | public CommitmentKeys DeriveLocalCommitmentKeys(uint localChannelKeyIndex, ChannelBasepoints localBasepoints, |
| | 21 | | ChannelBasepoints remoteBasepoints, ulong commitmentNumber) |
| | 22 | | { |
| | 23 | | // Get our per-commitment point for this commitment number from the signer |
| 0 | 24 | | var perCommitmentPoint = _lightningSigner.GetPerCommitmentPoint(localChannelKeyIndex, commitmentNumber); |
| | 25 | |
|
| | 26 | | // Get our per-commitment secret from the signer |
| 0 | 27 | | var perCommitmentSecret = _lightningSigner.ReleasePerCommitmentSecret(localChannelKeyIndex, commitmentNumber); |
| | 28 | |
|
| | 29 | | // For our local commitment transaction: |
| | 30 | | // - localpubkey = our payment_basepoint + SHA256(our_per_commitment_point || our_payment_basepoint) * G |
| 0 | 31 | | var localPubKey = _keyDerivationService.DerivePublicKey(localBasepoints.PaymentBasepoint, perCommitmentPoint); |
| | 32 | |
|
| | 33 | | // - local_delayedpubkey = our delayed_payment_basepoint + SHA256(our_per_commitment_point || our_delayed_paymen |
| 0 | 34 | | var localDelayedPubKey = |
| 0 | 35 | | _keyDerivationService.DerivePublicKey(localBasepoints.DelayedPaymentBasepoint, perCommitmentPoint); |
| | 36 | |
|
| | 37 | | // - local_htlcpubkey = our htlc_basepoint + SHA256(our_per_commitment_point || our_htlc_basepoint) * G |
| 0 | 38 | | var localHtlcPubKey = _keyDerivationService.DerivePublicKey(localBasepoints.HtlcBasepoint, perCommitmentPoint); |
| | 39 | |
|
| | 40 | | // - remote_htlcpubkey = their htlc_basepoint + SHA256(our_per_commitment_point || their_htlc_basepoint) * G |
| 0 | 41 | | var remoteHtlcPubKey = |
| 0 | 42 | | _keyDerivationService.DerivePublicKey(remoteBasepoints.HtlcBasepoint, perCommitmentPoint); |
| | 43 | |
|
| | 44 | | // - revocationpubkey = derived from their revocation_basepoint and our per_commitment_point |
| | 45 | | // This allows them to revoke our commitment if we broadcast an old one |
| 0 | 46 | | var revocationPubKey = |
| 0 | 47 | | _keyDerivationService.DeriveRevocationPubKey(remoteBasepoints.RevocationBasepoint, perCommitmentPoint); |
| | 48 | |
|
| | 49 | | // - remotepubkey = simply their payment_basepoint (NOT derived!) |
| 0 | 50 | | var remotePubKey = remoteBasepoints.PaymentBasepoint; |
| | 51 | |
|
| 0 | 52 | | return new CommitmentKeys( |
| 0 | 53 | | localPubKey, // localpubkey (for to_local output) |
| 0 | 54 | | localDelayedPubKey, // local_delayedpubkey (for to_local output with delay) |
| 0 | 55 | | revocationPubKey, // revocationpubkey (allows them to revoke our commitment) |
| 0 | 56 | | localHtlcPubKey, // local_htlcpubkey (for our HTLC outputs) |
| 0 | 57 | | remoteHtlcPubKey, // remote_htlcpubkey (for their HTLC outputs) |
| 0 | 58 | | perCommitmentPoint, // our per_commitment_point |
| 0 | 59 | | perCommitmentSecret // our per_commitment_secret |
| 0 | 60 | | ); |
| | 61 | | } |
| | 62 | |
|
| | 63 | | /// <inheritdoc /> |
| | 64 | | public CommitmentKeys DeriveRemoteCommitmentKeys(uint localChannelKeyIndex, ChannelBasepoints localBasepoints, |
| | 65 | | ChannelBasepoints remoteBasepoints, |
| | 66 | | CompactPubKey remotePerCommitmentPoint, ulong commitmentNumber) |
| | 67 | | { |
| | 68 | | // For their commitment transaction, we use their provided per-commitment point |
| | 69 | | // This should be provided by them via commitment_signed or update messages |
| | 70 | |
|
| | 71 | | // For their remote commitment transaction: |
| | 72 | | // - localpubkey (from their perspective) = their payment_basepoint + SHA256(their_per_commitment_point || their |
| 0 | 73 | | var theirLocalPubKey = _keyDerivationService.DerivePublicKey( |
| 0 | 74 | | remoteBasepoints.PaymentBasepoint, remotePerCommitmentPoint); |
| | 75 | |
|
| | 76 | | // - local_delayedpubkey (from their perspective) = their delayed_payment_basepoint + SHA256(their_per_commitmen |
| 0 | 77 | | var theirDelayedPubKey = _keyDerivationService.DerivePublicKey( |
| 0 | 78 | | remoteBasepoints.DelayedPaymentBasepoint, remotePerCommitmentPoint); |
| | 79 | |
|
| | 80 | | // - revocationpubkey = derived from our revocation_basepoint and their per_commitment_point |
| | 81 | | // This allows us to revoke their commitment if they broadcast an old one |
| 0 | 82 | | var revocationPubKey = _keyDerivationService.DeriveRevocationPubKey( |
| 0 | 83 | | localBasepoints.RevocationBasepoint, remotePerCommitmentPoint); |
| | 84 | |
|
| | 85 | | // - local_htlcpubkey (from their perspective) = their htlc_basepoint + SHA256(their_per_commitment_point || the |
| 0 | 86 | | var theirHtlcPubKey = _keyDerivationService.DerivePublicKey( |
| 0 | 87 | | remoteBasepoints.HtlcBasepoint, remotePerCommitmentPoint); |
| | 88 | |
|
| | 89 | | // - remote_htlcpubkey (from their perspective) = our htlc_basepoint + SHA256(their_per_commitment_point || our_ |
| 0 | 90 | | var ourHtlcPubKey = _keyDerivationService.DerivePublicKey( |
| 0 | 91 | | localBasepoints.HtlcBasepoint, remotePerCommitmentPoint); |
| | 92 | |
|
| | 93 | | // - remotepubkey (from their perspective) = simply our payment_basepoint (NOT derived!) |
| 0 | 94 | | var ourPubKey = localBasepoints.PaymentBasepoint; |
| | 95 | |
|
| 0 | 96 | | return new CommitmentKeys( |
| 0 | 97 | | theirLocalPubKey, // localpubkey (from their perspective, for their to_local output) |
| 0 | 98 | | theirDelayedPubKey, // local_delayedpubkey (from their perspective) |
| 0 | 99 | | revocationPubKey, // revocationpubkey (allows us to revoke their commitment) |
| 0 | 100 | | theirHtlcPubKey, // local_htlcpubkey (from their perspective) |
| 0 | 101 | | ourHtlcPubKey, // remote_htlcpubkey (from their perspective) |
| 0 | 102 | | remotePerCommitmentPoint, // their per_commitment_point |
| 0 | 103 | | null // We don't have their secret |
| 0 | 104 | | ); |
| | 105 | | } |
| | 106 | | } |