ddk_manager/
lib.rs

1//! # Library providing data structures and functions supporting the execution
2//! and management of DLC.
3
4#![crate_name = "ddk_manager"]
5// Coding conventions
6#![forbid(unsafe_code)]
7#![deny(non_upper_case_globals)]
8#![deny(non_camel_case_types)]
9#![deny(non_snake_case)]
10#![deny(unused_mut)]
11#![deny(dead_code)]
12#![deny(unused_imports)]
13#![deny(missing_docs)]
14
15#[macro_use]
16extern crate dlc_messages;
17
18pub mod chain_monitor;
19pub mod channel;
20pub mod channel_updater;
21pub mod contract;
22pub mod contract_updater;
23mod conversion_utils;
24pub mod error;
25pub mod manager;
26pub mod payout_curve;
27mod utils;
28
29use bitcoin::psbt::Psbt;
30use bitcoin::{Address, Block, OutPoint, ScriptBuf, Transaction, TxOut, Txid};
31use chain_monitor::ChainMonitor;
32use channel::offered_channel::OfferedChannel;
33use channel::signed_channel::{SignedChannel, SignedChannelStateType};
34use channel::Channel;
35use contract::PreClosedContract;
36use contract::{offered_contract::OfferedContract, signed_contract::SignedContract, Contract};
37use dlc_messages::impl_dlc_writeable;
38use dlc_messages::oracle_msgs::{OracleAnnouncement, OracleAttestation};
39use dlc_messages::ser_impls::{read_address, write_address};
40use error::Error;
41use lightning::ln::msgs::DecodeError;
42use lightning::util::ser::{Readable, Writeable, Writer};
43use secp256k1_zkp::{PublicKey, SecretKey, Signing};
44use secp256k1_zkp::{Secp256k1, XOnlyPublicKey};
45use std::collections::HashMap;
46use std::ops::Deref;
47use std::sync::RwLock;
48
49/// Type alias for a contract id.
50pub type ContractId = [u8; 32];
51
52/// Type alias for a keys id.
53pub type KeysId = [u8; 32];
54
55/// Type alias for a channel id.
56pub type ChannelId = [u8; 32];
57
58/// Time trait to provide current unix time. Mainly defined to facilitate testing.
59pub trait Time {
60    /// Must return the unix epoch corresponding to the current time.
61    fn unix_time_now(&self) -> u64;
62}
63
64/// Provide current time through `SystemTime`.
65pub struct SystemTimeProvider {}
66
67impl Time for SystemTimeProvider {
68    fn unix_time_now(&self) -> u64 {
69        let now = std::time::SystemTime::now();
70        now.duration_since(std::time::UNIX_EPOCH)
71            .expect("Unexpected time error")
72            .as_secs()
73    }
74}
75
76/// Provides signing related functionalities.
77pub trait ContractSigner: Clone {
78    /// Get the public key associated with the [`ContractSigner`].
79    fn get_public_key<C: Signing>(&self, secp: &Secp256k1<C>) -> Result<PublicKey, Error>;
80    /// Returns the secret key associated with the [`ContractSigner`].
81    // todo: remove this method and add create_adaptor_signature to the trait
82    fn get_secret_key(&self) -> Result<SecretKey, Error>;
83}
84
85/// Simple sample implementation of [`ContractSigner`].
86#[derive(Debug, Copy, Clone)]
87pub struct SimpleSigner {
88    secret_key: SecretKey,
89}
90
91impl SimpleSigner {
92    /// Creates a new [`SimpleSigner`] from the provided secret key.
93    pub fn new(secret_key: SecretKey) -> Self {
94        Self { secret_key }
95    }
96}
97
98impl ContractSigner for SimpleSigner {
99    fn get_public_key<C: Signing>(&self, secp: &Secp256k1<C>) -> Result<PublicKey, Error> {
100        Ok(self.secret_key.public_key(secp))
101    }
102
103    fn get_secret_key(&self) -> Result<SecretKey, Error> {
104        Ok(self.secret_key)
105    }
106}
107
108impl ContractSigner for SecretKey {
109    fn get_public_key<C: Signing>(&self, secp: &Secp256k1<C>) -> Result<PublicKey, Error> {
110        Ok(self.public_key(secp))
111    }
112
113    fn get_secret_key(&self) -> Result<SecretKey, Error> {
114        Ok(*self)
115    }
116}
117
118/// Derives a [`ContractSigner`] from a [`ContractSignerProvider`] and a `contract_keys_id`.
119pub trait ContractSignerProvider {
120    /// A type which implements [`ContractSigner`]
121    type Signer: ContractSigner;
122
123    /// Create a keys id for deriving a `Signer`.
124    fn derive_signer_key_id(&self, is_offer_party: bool, temp_id: [u8; 32]) -> [u8; 32];
125
126    /// Derives the private key material backing a `Signer`.
127    fn derive_contract_signer(&self, key_id: [u8; 32]) -> Result<Self::Signer, Error>;
128
129    /// Get the secret key associated with the provided public key.
130    ///
131    /// Only used for Channels.
132    fn get_secret_key_for_pubkey(&self, pubkey: &PublicKey) -> Result<SecretKey, Error>;
133    /// Generate a new secret key and store it in the wallet so that it can later be retrieved.
134    ///
135    /// Only used for Channels.
136    fn get_new_secret_key(&self) -> Result<SecretKey, Error>;
137}
138
139/// Wallet trait to provide functionalities related to generating, storing and
140/// managing bitcoin addresses and UTXOs.
141pub trait Wallet {
142    /// Returns a new (unused) address.
143    fn get_new_address(&self) -> Result<Address, Error>;
144    /// Returns a new (unused) change address.
145    fn get_new_change_address(&self) -> Result<Address, Error>;
146    /// Get a set of UTXOs to fund the given amount.
147    fn get_utxos_for_amount(
148        &self,
149        amount: u64,
150        fee_rate: u64,
151        lock_utxos: bool,
152    ) -> Result<Vec<Utxo>, Error>;
153    /// Import the provided address.
154    fn import_address(&self, address: &Address) -> Result<(), Error>;
155    /// Signs a transaction input
156    fn sign_psbt_input(&self, psbt: &mut Psbt, input_index: usize) -> Result<(), Error>;
157    /// Unlock reserved utxo
158    fn unreserve_utxos(&self, outpoints: &[OutPoint]) -> Result<(), Error>;
159}
160
161#[async_trait::async_trait]
162/// Blockchain trait provides access to the bitcoin blockchain.
163pub trait Blockchain {
164    /// Broadcast the given transaction to the bitcoin network.
165    async fn send_transaction(&self, transaction: &Transaction) -> Result<(), Error>;
166    /// Returns the network currently used (mainnet, testnet or regtest).
167    fn get_network(&self) -> Result<bitcoin::Network, Error>;
168    /// Returns the height of the blockchain
169    async fn get_blockchain_height(&self) -> Result<u64, Error>;
170    /// Returns the block at given height
171    async fn get_block_at_height(&self, height: u64) -> Result<Block, Error>;
172    /// Get the transaction with given id.
173    async fn get_transaction(&self, tx_id: &Txid) -> Result<Transaction, Error>;
174    /// Get the number of confirmation for the transaction with given id.
175    async fn get_transaction_confirmations(&self, tx_id: &Txid) -> Result<u32, Error>;
176}
177
178/// Storage trait provides functionalities to store and retrieve DLCs.
179pub trait Storage {
180    /// Returns the contract with given id if found.
181    fn get_contract(&self, id: &ContractId) -> Result<Option<Contract>, Error>;
182    /// Return all contracts
183    fn get_contracts(&self) -> Result<Vec<Contract>, Error>;
184    /// Create a record for the given contract.
185    fn create_contract(&self, contract: &OfferedContract) -> Result<(), Error>;
186    /// Delete the record for the contract with the given id.
187    fn delete_contract(&self, id: &ContractId) -> Result<(), Error>;
188    /// Update the given contract.
189    fn update_contract(&self, contract: &Contract) -> Result<(), Error>;
190    /// Returns the set of contracts in offered state.
191    fn get_contract_offers(&self) -> Result<Vec<OfferedContract>, Error>;
192    /// Returns the set of contracts in signed state.
193    fn get_signed_contracts(&self) -> Result<Vec<SignedContract>, Error>;
194    /// Returns the set of confirmed contracts.
195    fn get_confirmed_contracts(&self) -> Result<Vec<SignedContract>, Error>;
196    /// Returns the set of contracts whos broadcasted cet has not been verified to be confirmed on
197    /// blockchain
198    fn get_preclosed_contracts(&self) -> Result<Vec<PreClosedContract>, Error>;
199    /// Update the state of the channel and optionally its associated contract
200    /// atomically.
201    fn upsert_channel(&self, channel: Channel, contract: Option<Contract>) -> Result<(), Error>;
202    /// Delete the channel with given [`ChannelId`] if any.
203    fn delete_channel(&self, channel_id: &ChannelId) -> Result<(), Error>;
204    /// Returns the channel with given [`ChannelId`] if any.
205    fn get_channel(&self, channel_id: &ChannelId) -> Result<Option<Channel>, Error>;
206    /// Returns the set of [`SignedChannel`] in the store. Returns only the one
207    /// with matching `channel_state` if set.
208    fn get_signed_channels(
209        &self,
210        channel_state: Option<SignedChannelStateType>,
211    ) -> Result<Vec<SignedChannel>, Error>;
212    /// Returns the set of channels in offer state.
213    fn get_offered_channels(&self) -> Result<Vec<OfferedChannel>, Error>;
214    /// Writes the [`ChainMonitor`] data to the store.
215    fn persist_chain_monitor(&self, monitor: &ChainMonitor) -> Result<(), Error>;
216    /// Returns the latest [`ChainMonitor`] in the store if any.
217    fn get_chain_monitor(&self) -> Result<Option<ChainMonitor>, Error>;
218}
219
220#[async_trait::async_trait]
221/// Oracle trait provides access to oracle information.
222pub trait Oracle {
223    /// Returns the public key of the oracle.
224    fn get_public_key(&self) -> XOnlyPublicKey;
225    /// Returns the announcement for the event with the given id if found.
226    async fn get_announcement(&self, event_id: &str) -> Result<OracleAnnouncement, Error>;
227    /// Returns the attestation for the event with the given id if found.
228    async fn get_attestation(&self, event_id: &str) -> Result<OracleAttestation, Error>;
229}
230
231/// Represents a UTXO.
232#[derive(Clone, Debug)]
233pub struct Utxo {
234    /// The TxOut containing the value and script pubkey of the referenced output.
235    pub tx_out: TxOut,
236    /// The outpoint containing the txid and vout of the referenced output.
237    pub outpoint: OutPoint,
238    /// The address associated with the referenced output.
239    pub address: Address,
240    /// The redeem script for the referenced output.
241    pub redeem_script: ScriptBuf,
242    /// Whether this Utxo has been reserved (and so should not be used to fund
243    /// a DLC).
244    pub reserved: bool,
245}
246
247impl_dlc_writeable!(Utxo, {
248    (tx_out, writeable),
249    (outpoint, writeable),
250    (address, {cb_writeable, write_address, read_address}),
251    (redeem_script, writeable),
252    (reserved, writeable)
253});
254
255/// A ContractSignerProvider that caches the signers
256pub struct CachedContractSignerProvider<SP: Deref, X>
257where
258    SP::Target: ContractSignerProvider<Signer = X>,
259{
260    pub(crate) signer_provider: SP,
261    pub(crate) cache: RwLock<HashMap<KeysId, X>>,
262}
263
264impl<SP: Deref, X> CachedContractSignerProvider<SP, X>
265where
266    SP::Target: ContractSignerProvider<Signer = X>,
267{
268    /// Create a new [`ContractSignerProvider`]
269    pub fn new(signer_provider: SP) -> Self {
270        Self {
271            signer_provider,
272            cache: RwLock::new(HashMap::new()),
273        }
274    }
275}
276
277impl<SP: Deref, X: ContractSigner> ContractSignerProvider for CachedContractSignerProvider<SP, X>
278where
279    SP::Target: ContractSignerProvider<Signer = X>,
280{
281    type Signer = X;
282
283    fn derive_signer_key_id(&self, is_offer_party: bool, temp_id: [u8; 32]) -> KeysId {
284        self.signer_provider
285            .derive_signer_key_id(is_offer_party, temp_id)
286    }
287
288    fn derive_contract_signer(&self, key_id: KeysId) -> Result<Self::Signer, Error> {
289        match self.cache.try_read().unwrap().get(&key_id) {
290            Some(signer) => Ok(signer.clone()),
291            None => self.signer_provider.derive_contract_signer(key_id),
292        }
293    }
294
295    fn get_secret_key_for_pubkey(&self, pubkey: &PublicKey) -> Result<SecretKey, Error> {
296        self.signer_provider.get_secret_key_for_pubkey(pubkey)
297    }
298
299    fn get_new_secret_key(&self) -> Result<SecretKey, Error> {
300        self.signer_provider.get_new_secret_key()
301    }
302}