Class ClaimPacket
- Namespace
- NArk.ArkadeIntents.Lightning
- Assembly
- NArk.ArkadeIntents.dll
Seals a receive swap's preimage to covclaimd, so the claim can be pushed while the client is offline without the solver ever learning the secret.
public static class ClaimPacket
- Inheritance
-
ClaimPacket
- Inherited Members
Remarks
The asymmetry is the point. On a receive swap the solver funds the Arkade side before the Lightning payment it is owed has settled, and it only gets paid when the preimage surfaces in a claim witness. If the solver could open this packet it could settle without ever paying out, so the encryption is to covclaimd's key — not the solver's — and the solver carries it as opaque bytes it cannot read.
The scheme is ECIES over secp256k1: an ephemeral key, ECDH, HKDF-SHA256, then AES-256-GCM with the ephemeral public key as additional data. One detail is easy to get wrong and impossible to catch locally — the ECDH shared secret is the 32-byte X coordinate alone, not the compressed point some libraries hand back.
Methods
NewAsync(string, IAesGcmCipher?, CancellationToken)
Generate a fresh 32-byte preimage and seal it — how a receive swap starts.
public static Task<SealedClaimPacket> NewAsync(string covclaimdPubKeyHex, IAesGcmCipher? cipher = null, CancellationToken cancellationToken = default)
Parameters
covclaimdPubKeyHexstringcovclaimd's compressed secp256k1 key, hex.
cipherIAesGcmCiphercancellationTokenCancellationToken
Returns
- Task<SealedClaimPacket>
The packet, the preimage and its payment hash.
PaymentHashOf(byte[])
The payment hash a preimage settles against: sha256(preimage), hex.
public static string PaymentHashOf(byte[] preimage)
Parameters
preimagebyte[]The 32-byte secret.
Returns
- string
64 lowercase hex characters.
Remarks
Needed on its own because sealing is optional: a client with no covclaimd sends no packet, and still has to name the hash its quote is requested against.
SealAsync(byte[], string, IAesGcmCipher?, CancellationToken)
Seal a preimage to covclaimd's public key.
public static Task<SealedClaimPacket> SealAsync(byte[] preimage, string covclaimdPubKeyHex, IAesGcmCipher? cipher = null, CancellationToken cancellationToken = default)
Parameters
preimagebyte[]The 32-byte secret the client chose.
covclaimdPubKeyHexstringcovclaimd's compressed secp256k1 key, from
GET /v1/preimage/covclaimd-pubkey. Read it live — covclaimd generates its own, so a hardcoded value goes stale silently.cipherIAesGcmCipherSupplies AES-GCM. Defaults to the platform's, which is right everywhere except a browser — see IAesGcmCipher.
cancellationTokenCancellationTokenCancels the encryption.
Returns
- Task<SealedClaimPacket>
The packet, the preimage and its payment hash.
Remarks
The ECDH shared secret is the 32-byte X coordinate, not the 33-byte compressed point. Keeping the parity byte still yields a well-formed key on both sides, so nothing local disagrees — only the remote AEAD tag check fails, and only once a live daemon sees it. The same trap exists in the JS reference, whose ECDH helper returns the compressed point by default.