dlc_manager/
lib.rs

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