# DLC Transactions It is recommended that all keys be generated/derived as specified [here](https://github.com/discreetlogcontracts/dlcspecs/blob/master/KeyDerivation.md#dlc-key-derivation). ## Funding Transaction ### Known Values * Local Funding Inputs: `List[TransactionInput]` * Local Change ScriptPubKey: `ScriptPubKey` * Local Funding Public Key: `ECPublicKey` * Remote Funding Inputs: `List[TransactionInput]` * Remote Change ScriptPubKey: `ScriptPubKey` * Remote Funding Public Key: `ECPublicKey` * nLockTime: `UInt32` * Total Local Collateral: `CurrencyUnit` * Total Remote Collateral: `CurrencyUnit` * Fee Rate: `FeeUnit` Where - Local something something Remote - The sum of each `Funding Inputs`' value is at least that of its `Total Collateral` - `Funding Public Key`s are both 33-byte compressed public keys - `nLockTime` is in the past (rather than just using 0) - for privacy purposes and also to prevent [fee snipping](https://github.com/zkSNACKs/WalletWasabi/issues/2500) - Both `Change ScriptPubKey`s must be either `P2WSH/P2WPKH`, or `P2SH-P2WSH/P2SH-P2WPKH` ### Global * nLockTime ### Inputs * Local Funding Inputs * Remote Funding Inputs ### Outputs * P2WSH(DLC Funding Output) * Local Change ScriptPubKey * Remote Change ScriptPubKey Where - `P2WSH(DLC Funding Output)`'s value is `Total Local Collateral + Total Remote Collateral + Computed CET Fee + Computed ToLocal Closing Fee` - `DLC Funding Output`'s script is OP_2 OP_2 OP_CHECKMULTISIG - Each `Change ScriptPubKey`'s value is at most that of its respective `Sum(Funding Inputs) - Total Collateral - Computed Fees - (Computed CET Fee + Computed ToLocal Closing Fee)/2` with `Computed Fees` being proportional to each party's total input weight and `Computed CET Fee` being the estimated fee for a [Contract Execution Transaction](#contract-execution-transaction) and `Computed ToLocal Closing Fee` being the estimated fee for a [Unilateral Closing Transaction](#ClosingUnilateral) ## Contract Execution Transaction ### Known Values * Oracle Signature Point: `ECPublicKey` * Local CET Public Key: `ECPublicKey` * Local Payout: `CurrencyUnit` * Remote CET Public Key: `ECPublicKey` * Remote Paytout: `CurrencyUnit` * nLockTime: `UInt32` * Timeout: `UInt32` * DLC Funding Output: `ScriptPubKey` * Fee Rate: `FeeUnit` Where - `Oracle Signature Point` is the 33-byte public key associated with this CET's outcome - Both `CET Public Key`s are 33-byte compressed public keys - `Local Paytout + Remote Payout = (DLC Funding Output).value` - `nLockTime` is set to the contract maturity time - `Timeout` is a CSV locktime after which [penalty transactions](#ClosingPenalty) are valid - `DLC Funding Output` is of the form [specified above](#FundingOutputs) ### Global * nLockTime ### Inputs * Input Spending(P2WSH(DLC Funding Output)) ### Outputs * P2WSH(ToLocalOutput) * ToRemoteOutput Where - `P2WSH(ToLocalOutput).value = Local Payout + Computed ToLocal Closing Fee` - `ToRemoteOutput.value = Remote Payout` - `ToLocalOutput`'s script is: OP_IF OP_ELSE OP_CHECKSEQUENCEVERIFY OP_DROP OP_ENDIF OP_CHECKSIG - Note that The addition in the if case is elliptic curve point addition - `ToRemoteOutput`'s script is: OP_0 Which is `P2WPKH(Remote CET Public Key)` ## Refund Transaction ### Known Values * Local Refund Public Key: `ECPublicKey` * Total Local Collateral: `CurrencyUnit` * Remote Refund Public Key: `ECPublicKey` * Total Remote Collateral: `CurrencyUnit` * Timeout: `UInt32` * DLC Funding Output: `ScriptPubKey` * Fee Rate: `FeeUnit` Where - Unlike CETs in a DLC, there is only one Refund Transaction that both parties share, similar to how there is only one [Funding Transaction](#funding-transaction) - Both `Refund Public Key`s are 33-byte compressed public keys - `Total Local Collateral + Total Remote Collateral = (DLC Funding Output).value` - `Timeout` is a CLTV locktime set well after the contract maturity time - `DLC Funding Output` is of the form [specified above](#FundingOutputs) ### Global * nLockTime is `Timeout` ### Inputs * Input Spending(P2WSH(DLC Funding Output)) ### Outputs * ToLocalOutput * ToRemoteOutput Where - `ToLocalOutput`'s value is `Total Local Collateral + RefundFeeDelta/2` - `ToRemoteOutput`'s value is `Total Remote Collateral + RefundFeeDelta/2` - `RefundFeeDelta = Computed CET Fee + Computed ToLocal Closing Fee - Computed Refund Tx Fee` (note that the Refund Transaction is smaller than any CET) - `ToLocalOutput`'s script is: OP_0 Which is `P2WPKH(Local Refund Public Key)` - `ToRemoteOutput`'s script is: OP_0 Which is `P2WPKH(Remote Refund Public Key)` ## Mutual Closing Transaction ### Known Values * Local Mutual Closing Public Key: `ECPublicKey` * Local Payout: `CurrencyUnit` * Remote Mutual Closing Public Key: `ECPublicKey` * Remote Payout: `CurrencyUnit` * nLockTime: `UInt32` * DLC Funding Output: `ScriptPubKey` * Fee Rate: `FeeUnit` Where - After the contract maturity time, Mutual Closing Transaction is created in cooperation for fee reduction and improvement in privacy - Both `Mutual Closing Public Key`s are 33-byte compressed public keys - `Local Payout = (Contract Execution Transaction Local Payout).value` - `Remote Payout = (Contract Execution Transaction Remote Payout).value` - `nLockTime` is in the past (rather than just using 0) - for privacy purposes and also to prevent [fee snipping](https://github.com/zkSNACKs/WalletWasabi/issues/2500) - `DLC Funding Output` is of the form [specified above](#FundingOutputs) ### Global * nLockTime ### Inputs * Input Spending(P2WSH(DLC Funding Output)) ### Outputs * ToLocalOutput * ToRemoteOutput Where - `ToLocalOutput's value is Local Payout + MutualClosingFeeDelta/2` - `ToRemoteOutput's value is Remote Payout + MutualClosingFeeDelta/2` - `MutualClosingFeeDelta = Computed CET Fee + Computed ToLocal Closing Fee - Computed MutualClosing Tx Fee (note that the Mutual Closing Transaction is smaller than any CET)` - `ToLocalOutput`'s script is: OP_0 Which is `P2WPKH(Local Mutual Closing Public Key)` - `ToRemoteOutput`'s script is: OP_0 Which is `P2WPKH(Remote Mutual Closing Public Key)` ## Closing Transaction (Unilateral) ### Known Values * Local Unilateral Public Key: `ECPublicKey` * nLockTime: `UInt32` * Local Payout: `CurrencyUnit` * ToLocalOutput: `ScriptPubKey` * Fee Rate: `FeeUnit` Where - `ToLocalOutput` is of the form [specified above](#CETOutputs) - `nLockTime` is in the past (rather than just using 0) - for privacy purposes and also to prevent [fee snipping](https://github.com/zkSNACKs/WalletWasabi/issues/2500) ### Global * nLockTime ### Inputs * Input Spending(P2WSH(ToLocalOutput)) ### Outputs * P2WPKH(Local Unilateral Public Key) Where - `P2WPKH(Local Unilateral Public Key)`'s value is `Local Payout` ## Closing Transaction (Penalty) ### Known Values * Local Penalty Public Key: `ECPublicKey` * nLockTime: `UInt32` * Remote's ToLocalOutput: `ScriptPubKey` * Fee Rate: `FeeUnit` Where - `Remote's ToLocalOutput` is of the form [specified above](#CETOutputs) - `nLockTime` is in the past (rather than just using 0) - for privacy purposes and also to prevent [fee snipping](https://github.com/zkSNACKs/WalletWasabi/issues/2500) ### Global * nLockTime ### Inputs * Input Spending(P2WSH(Remote's ToLocalOutput)) ### Outputs * P2WPKH(Local Justice Public Key) Where - `P2WPKH(Local Penalty Public Key)`'s value is `P2WSH(Remote's ToLocalOutput).value - fee`