improve documentation

This commit is contained in:
conduition
2024-03-20 01:43:59 +00:00
parent cc0fb0e15c
commit 29c7a8a16b
6 changed files with 150 additions and 10 deletions

3
demo/README.md Normal file
View File

@@ -0,0 +1,3 @@
# Demo
This folder contains some unfinished code for a client/server implementation of the Ticketed DLC protocol. Due to time constraints and the complexity involved, and since I'm working solo on this, I haven't yet been able to complete this implementation.

View File

@@ -97,7 +97,11 @@ pub enum Outcome {
/// Points to a situation where a player wins a payout from the DLC.
#[derive(Clone, Copy, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)]
pub struct WinCondition {
/// Indicates the outcome which would've been attested to by the oracle.
pub outcome: Outcome,
/// Indicates the particular player who would be paid out as a winner
/// in this outcome. Because outputs are sorted by player, this also
/// is the index of this player's output in the split transaction.
pub player_index: PlayerIndex,
}
@@ -297,6 +301,8 @@ impl ContractParameters {
Some(win_conditions_to_sign)
}
/// Return a blank [`SigMap`] illustrating the different outcomes and
/// win conditions which a given pubkey should sign.
pub fn sigmap_for_pubkey(&self, pubkey: Point) -> Option<SigMap<()>> {
let win_conditions = self.win_conditions_controlled_by_pubkey(pubkey)?;
let sigmap = SigMap {
@@ -346,11 +352,16 @@ impl ContractParameters {
/// outcome transaction, and for different [`WinCondition`]s within each split transaction.
#[derive(Debug, Clone, Eq, PartialEq, Default, Serialize, Deserialize)]
pub struct SigMap<T> {
/// Corresponds to the set of outcome transactions which the player needs to sign.
pub by_outcome: BTreeMap<Outcome, T>,
/// Corresponds to the set of split transaction spending conditions which the
/// player needs to sign.
pub by_win_condition: BTreeMap<WinCondition, T>,
}
impl<T> SigMap<T> {
/// Map each outcome and win condition to values of a specific type using
/// distinct map functions.
pub fn map<V, F1, F2>(self, map_outcomes: F1, map_win_conditions: F2) -> SigMap<V>
where
F1: Fn(Outcome, T) -> V,
@@ -370,6 +381,7 @@ impl<T> SigMap<T> {
}
}
/// Map each outcome and win condition to values of a specific type.
pub fn map_values<V, F>(self, mut map_fn: F) -> SigMap<V>
where
F: FnMut(T) -> V,
@@ -388,6 +400,7 @@ impl<T> SigMap<T> {
}
}
/// Return a `SigMap` which contains references to the values held by this `SigMap`.
pub fn by_ref(&self) -> SigMap<&T> {
SigMap {
by_outcome: self.by_outcome.iter().map(|(&k, v)| (k, v)).collect(),

View File

@@ -1,3 +1,6 @@
//! This module contains utilities for constructing LN-compatible preimages
//! and SHA256 hashes.
use sha2::Digest as _;
/// The size for ticket preimages.

View File

@@ -1,6 +1,7 @@
//! Crate documentation is TODO.
//!
//! See [the Github README](https://github.com/conduition/dlctix).
#![warn(missing_docs)]
#[cfg(test)]
mod regtest;
@@ -142,6 +143,8 @@ impl SigningSessionState for NonceSharingRound {}
impl SigningSessionState for PartialSignatureSharingRound {}
/// This is a state machine to manage signing the various transactions in a [`TicketedDLC`].
/// The generic parameter `S` determines which of the two stages of the signing session
/// we are in.
pub struct SigningSession<S: SigningSessionState> {
dlc: TicketedDLC,
our_public_key: Point,
@@ -172,12 +175,8 @@ impl SigningSession<NonceSharingRound> {
let base_sigmap = dlc.params.sigmap_for_pubkey(our_public_key).ok_or(Error)?;
let our_secret_nonces = base_sigmap.map_values(|_| {
SecNonce::build(&mut rng)
.with_seckey(signing_key)
// .with_extra_info(&self.dlc.params.serialize()) // TODO
.build()
});
let our_secret_nonces =
base_sigmap.map_values(|_| SecNonce::build(&mut rng).with_seckey(signing_key).build());
let our_public_nonces = our_secret_nonces
.by_ref()
@@ -659,6 +658,10 @@ impl SignedContract {
Ok(split_tx)
}
/// Returns prevout information for the market maker to create and sign an
/// outcome-reclaim transaction.
///
/// See [SignedContract::sign_outcome_reclaim_tx_input] for more info on the outcome-reclaim TX.
pub fn outcome_reclaim_tx_input_and_prevout<'a>(
&'a self,
outcome: &Outcome,
@@ -670,6 +673,10 @@ impl SignedContract {
)
}
/// Returns prevout information for the market maker to create and sign an
/// outcome-close transaction.
///
/// See [SignedContract::sign_outcome_close_tx_input] for more info on the outcome-close TX.
pub fn outcome_close_tx_input_and_prevout<'a>(
&'a self,
outcome: &Outcome,
@@ -677,6 +684,9 @@ impl SignedContract {
contract::outcome::outcome_tx_prevout(&self.dlc.outcome_tx_build, outcome, 0)
}
/// Returns prevout information for a player to create and sign a split-win transaction.
///
/// See [SignedContract::sign_split_win_tx_input] for more info on the split-win TX.
pub fn split_win_tx_input_and_prevout<'a>(
&'a self,
win_cond: &WinCondition,
@@ -689,6 +699,10 @@ impl SignedContract {
)
}
/// Returns prevout information for the market maker to create and sign a split-reclaim
/// transaction.
///
/// See [SignedContract::sign_split_reclaim_tx_input] for more info on the split-reclaim TX.
pub fn split_reclaim_tx_input_and_prevout<'a>(
&'a self,
win_cond: &WinCondition,
@@ -701,6 +715,10 @@ impl SignedContract {
)
}
/// Returns prevout information for the market maker to create and sign a
/// split-sellback transaction.
///
/// See [SignedContract::sign_split_sellback_tx_input] for more info on the split-sellback TX.
pub fn split_sellback_tx_input_and_prevout<'a>(
&'a self,
win_cond: &WinCondition,
@@ -708,6 +726,10 @@ impl SignedContract {
contract::split::split_tx_prevout(&self.dlc.params, &self.dlc.split_tx_build, win_cond, 0)
}
/// Returns prevout information for the market maker to create and sign a
/// split-close transaction.
///
/// See [SignedContract::sign_split_close_tx_input] for more info on the split-close TX.
pub fn split_close_tx_input_and_prevout<'a>(
&'a self,
win_cond: &WinCondition,
@@ -715,6 +737,10 @@ impl SignedContract {
contract::split::split_tx_prevout(&self.dlc.params, &self.dlc.split_tx_build, win_cond, 0)
}
/// Returns an input weight prediction value for the witnessed input of an
/// outcome-reclaim TX, which reclaims funds from the given outcome's outcome TX.
///
/// See [SignedContract::sign_outcome_reclaim_tx_input] for more info on the outcome-reclaim TX.
pub fn outcome_reclaim_tx_input_weight(
&self,
outcome: &Outcome,
@@ -726,8 +752,11 @@ impl SignedContract {
.map(|outcome_spend_info| outcome_spend_info.input_weight_for_reclaim_tx())
}
/// Returns an input weight prediction value for the witnessed input of a split-win TX.
/// All split-win TX inputs have the same weight.
///
/// See [SignedContract::sign_split_win_tx_input] for more info on the split-win TX.
pub fn split_win_tx_input_weight(&self) -> InputWeightPrediction {
// All win TXs have the same input weight.
self.dlc
.split_tx_build
.split_spend_infos()
@@ -737,6 +766,12 @@ impl SignedContract {
.input_weight_for_win_tx()
}
/// Returns an input weight prediction value for the witnessed input of a split-reclaim TX.
/// All split-reclaim TX inputs have the same weight.
///
/// See [SignedContract::sign_split_reclaim_tx_input] for more info on the split-reclaim TX.
///
/// TODO: this should be a constant covered by tests.
pub fn split_reclaim_tx_input_weight(&self) -> InputWeightPrediction {
// All reclaim TXs have the same input weight.
self.dlc
@@ -748,8 +783,13 @@ impl SignedContract {
.input_weight_for_reclaim_tx()
}
/// Returns an input weight prediction value for the witnessed input of a split-sellback TX.
/// All split-sellback TX inputs have the same weight.
///
/// See [SignedContract::sign_split_sellback_tx_input] for more info on the split-sellback TX.
///
/// TODO: this should be a constant covered by tests.
pub fn split_sellback_tx_input_weight(&self) -> InputWeightPrediction {
// All sellback TXs have the same input weight.
self.dlc
.split_tx_build
.split_spend_infos()
@@ -759,6 +799,17 @@ impl SignedContract {
.input_weight_for_sellback_tx()
}
/// Returns an input weight prediction value for the witnessed input of a split-close TX.
/// All split-close TX inputs have the same weight, which is
/// [`InputWeightPrediction::P2TR_KEY_DEFAULT_SIGHASH`].
///
/// See [SignedContract::sign_split_close_tx_input] for more info on the split-close TX.
///
/// TODO: this should be a constant alias.
pub fn split_close_tx_input_weight(&self) -> InputWeightPrediction {
InputWeightPrediction::P2TR_KEY_DEFAULT_SIGHASH
}
pub(crate) fn unchecked_sign_outcome_reclaim_tx_input<T: Borrow<TxOut>>(
&self,
outcome: &Outcome,
@@ -785,6 +836,16 @@ impl SignedContract {
Ok(())
}
/// Sign an outcome-reclaim transaction which spends the outcome TX output to the control
/// of the market maker.
///
/// The outcome-reclaim TX should be used if none of the outcome winners purchased their ticket
/// preimage, and so the market maker can reclaim his money before the split transaction
/// splits it into multiple smaller UTXOs.
///
/// The market maker can only publish an outcome-reclaim TX once the outcome transaction has at
/// least [`2 * relative_locktime_block_delta`][ContractParameters::relative_locktime_block_delta]
/// confirmations.
pub fn sign_outcome_reclaim_tx_input<T: Borrow<TxOut>>(
&self,
outcome: &Outcome,
@@ -818,11 +879,20 @@ impl SignedContract {
)
}
/// Sign a cooperative closing transaction which spends the outcome transaction output.
/// Sign a cooperative closing transaction which spends the outcome transaction output
/// back to the market maker's control.
///
/// The outcome-close TX should be used when all outcome winners purchased their ticket
/// preimage, and the market maker has paid each winner their winnings out-of-band.
///
/// The market maker can use this method once they have issued off-chain payouts to
/// all winning players for an outcome. Once the players have their payouts, they can
/// send their secret keys to the market maker to let him reclaim all the on-chain
/// capital.
///
/// The market maker can only publish an outcome-close TX once all winning players have
/// given the market maker their secret keys, which they should only do if they have been
/// paid out completely.
pub fn sign_outcome_close_tx_input<T: Borrow<TxOut>>(
&self,
outcome: &Outcome,
@@ -899,6 +969,17 @@ impl SignedContract {
Ok(())
}
/// Sign a transaction which spends a split transaction output to the control of a player
/// who must know their ticket preimage.
///
/// The split-win TX should be used by a player to enforce the outcome payout on-chain.
/// Ideally, players would be paid out off-chain or using cross-chain HTLCs. However,
/// the split-win TX is the fallback option which guarantees a player receives a majority
/// of their payout (minus mining fees).
///
/// The player can only publish a split-win TX once the split transaction has at
/// least [`relative_locktime_block_delta`][ContractParameters::relative_locktime_block_delta]
/// confirmations.
pub fn sign_split_win_tx_input<T: Borrow<TxOut>>(
&self,
win_cond: &WinCondition,
@@ -969,6 +1050,15 @@ impl SignedContract {
Ok(())
}
/// Signs a transaction which spends a split transaction output to the market
/// maker's control.
///
/// The split-reclaim TX should be used by the market maker if a specific player did not
/// buy their ticket preimage, and so the market maker can reclaim the winnings himself.
///
/// The market maker can only publish a split-reclaim TX once the split transaction has at
/// least [`2 * relative_locktime_block_delta`][ContractParameters::relative_locktime_block_delta]
/// confirmations.
pub fn sign_split_reclaim_tx_input<T: Borrow<TxOut>>(
&self,
win_cond: &WinCondition,
@@ -1002,6 +1092,21 @@ impl SignedContract {
)
}
/// Signs a transaction which spends a split transaction output to the market
/// maker's control.
///
/// A split-sellback TX should be used when an outcome winner purchased their ticket
/// preimage, and the market maker has paid the winner their winnings out-of-band in
/// exchange for the player's payout preimage.
///
/// The market maker can only publish a split-sellback TX once a player has given
/// the market maker their payout preimage, which they should only do if they have been
/// paid out completely.
///
/// The only distinction between a split-sellback and a split-close TX is whether the
/// market maker has been given the player's signing key. If so, then the market maker
/// should use the split-close TX because it is more efficient and private than the
/// split-sellback TX.
pub fn sign_split_sellback_tx_input<T: Borrow<TxOut>>(
&self,
win_cond: &WinCondition,
@@ -1051,9 +1156,22 @@ impl SignedContract {
}
/// Sign a cooperative closing transaction which spends a player's split transaction output.
///
/// The split-close TX should be used when an outcome winner purchased their ticket
/// preimage, and the market maker has paid the winner their winnings out-of-band.
///
/// The market maker can use this method once they have issued off-chain payouts to this
/// winning player. Once the player has her off-chain payout, they can send their secret
/// winning player. Once the player has her off-chain payout, she can send their secret
/// key to the market maker to let him reclaim all the on-chain capital efficiently.
///
/// The market maker can only publish a split-close TX once a player has given
/// the market maker their secret key, which they should only do if they have been
/// paid out completely.
///
/// The only distinction between a split-sellback and a split-close TX is whether the
/// market maker has been given the player's signing key. If so, then the market maker
/// should use the split-close TX because it is more efficient and private than the
/// split-sellback TX.
pub fn sign_split_close_tx_input<T: Borrow<TxOut>>(
&self,
win_cond: &WinCondition,

View File

@@ -8,6 +8,7 @@ use crate::serialization;
/// who wishes to profit by leveraging their capital.
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
pub struct MarketMaker {
/// The market maker's pubkey.
pub pubkey: Point,
}

View File

@@ -1,3 +1,5 @@
//! This module contains integration tests which leverage a remote Bitcoin regtest node.
use crate::*;
use bitcoincore_rpc::{jsonrpc::serde_json, Auth, Client as BitcoinClient, RpcApi};