Table of Contents

Class SwapScriptValues

Namespace
NArk.ArkadeIntents.Lightning
Assembly
NArk.ArkadeIntents.dll

The conversions a swap's script parameters have to go through before they can be committed to.

public static class SwapScriptValues
Inheritance
SwapScriptValues
Inherited Members

Remarks

Small, but each one is a place where a plausible-looking value is silently the wrong one — a locktime a verifier reads as a block height, a delay BIP68 rounds down, or the invoice's hash used where the script commits to a different digest of it.

Fields

LocktimeThreshold

BIP65: at or above this value a locktime is a unix timestamp rather than a block height.

public const uint LocktimeThreshold = 500000000

Field Value

uint

SequenceGranularitySeconds

BIP68 encodes relative time in units of 512 seconds.

public const uint SequenceGranularitySeconds = 512

Field Value

uint

SoloRefundHeadroomSeconds

How far the funder's solo refund opens after the claim, in seconds.

public const uint SoloRefundHeadroomSeconds = 4096

Field Value

uint

Remarks

The one leaf a funder can spend without anybody else, so the only one whose timing can take money from a claimant who holds the preimage and did nothing wrong. Sized for what reaching the claim actually costs with the Arkade server gone — an unroll broadcast per chain step, each waiting on a confirmation, then the CSV spend. A single granularity tick never covered that. Must match the reference solver's SOLO_REFUND_HEADROOM_SECONDS, and is a whole number of BIP68 units so that stacking it cannot silently re-round.

Methods

CeilToGranularity(uint)

Round a duration up to the next whole BIP68 512-second unit.

public static uint CeilToGranularity(uint seconds)

Parameters

seconds uint

The duration to round, in seconds.

Returns

uint

The smallest multiple of 512 greater than or equal to seconds.

Remarks

Up, never down: rounding a required delay down produces a script the server accepts at funding and rejects at spend, which surfaces only once there is money behind it.

PreimageHashFromPaymentHash(uint256)

The script's 20-byte hash, taken straight from a decoded invoice: the invoice carries sha256(P), the script's HASH160 branch commits to ripemd160(sha256(P)).

public static byte[] PreimageHashFromPaymentHash(uint256 paymentHash)

Parameters

paymentHash uint256

The invoice's payment hash.

Returns

byte[]

RIPEMD160 of the payment hash, big-endian.

Remarks

Always prefer this over the byte-array overload when the value came from a BOLT11. NBitcoin.uint256 hands out its bytes little-endian by default, which is the opposite of how a payment hash is written, hashed and agreed upon — and reversing it produces a perfectly well-formed script committing to a hash no preimage will ever open. Nothing rejects that locally: it surfaces as a lockup address the counterparty does not recognise, and would surface as unspendable funds if anything ever funded it.

PreimageHashFromPaymentHash(byte[])

Bridge a BOLT11 payment hash to the 20-byte hash the script commits to.

public static byte[] PreimageHashFromPaymentHash(byte[] paymentHash)

Parameters

paymentHash byte[]

The payment hash, big-endian — as written, not as ToBytes(bool) defaults to.

Returns

byte[]

The 20-byte HASH160 the covenant script commits to.

Remarks

This is why the maker never needs to see the preimage: it can commit to the hash of a secret it does not hold, and paying the invoice is what reveals that secret to whoever claims.

Exceptions

ArgumentException

The payment hash is not 32 bytes.