Skip to content

Commit

Permalink
feat: use bdk-macros for async dlc-manager
Browse files Browse the repository at this point in the history
  • Loading branch information
bennyhodl committed Oct 8, 2024
1 parent 0d16b4b commit ad64fea
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 39 deletions.
5 changes: 4 additions & 1 deletion dlc-manager/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,22 @@ std = ["dlc/std", "dlc-messages/std", "dlc-trie/std", "bitcoin/std", "lightning/
fuzztarget = ["rand_chacha"]
parallel = ["dlc-trie/parallel"]
use-serde = ["serde", "dlc/use-serde", "dlc-messages/use-serde", "dlc-trie/use-serde"]
async-interface = ["dep:async-trait"]

[dependencies]
async-trait = "0.1.50"
async-trait = { version = "0.1.50", optional = true }
bitcoin = { version = "0.32.2", default-features = false }
dlc = { version = "0.6.0", default-features = false, path = "../dlc" }
dlc-messages = { version = "0.6.0", default-features = false, path = "../dlc-messages" }
dlc-trie = { version = "0.6.0", default-features = false, path = "../dlc-trie" }
# dlc-macros = { version = "0.1.0", path = "../dlc-macros" }
hex = { package = "hex-conservative", version = "0.1" }
lightning = { version = "0.0.124", default-features = false, features = ["grind_signatures"] }
log = "0.4.14"
rand_chacha = {version = "0.3.1", optional = true}
secp256k1-zkp = {version = "0.11.0"}
serde = {version = "1.0", optional = true}
bdk-macros = "0.6.0"

[dev-dependencies]
bitcoin-rpc-provider = {path = "../bitcoin-rpc-provider"}
Expand Down
4 changes: 4 additions & 0 deletions dlc-manager/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#![deny(unused_imports)]
#![deny(missing_docs)]

#[cfg(feature = "async-interface")]
extern crate async_trait;
extern crate bitcoin;
extern crate dlc;
Expand All @@ -36,6 +37,8 @@ pub mod manager;
pub mod payout_curve;
mod utils;

#[cfg(feature = "async-interface")]
use async_trait::async_trait;
use bitcoin::psbt::Psbt;
use bitcoin::{Address, Block, OutPoint, ScriptBuf, Transaction, TxOut, Txid};
use chain_monitor::ChainMonitor;
Expand Down Expand Up @@ -226,6 +229,7 @@ pub trait Storage {
}

/// Oracle trait provides access to oracle information.
#[bdk_macros::maybe_async]
pub trait Oracle {
/// Returns the public key of the oracle.
fn get_public_key(&self) -> XOnlyPublicKey;
Expand Down
93 changes: 55 additions & 38 deletions dlc-manager/src/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use crate::contract_updater::{accept_contract, verify_accepted_and_sign_contract
use crate::error::Error;
use crate::utils::get_object_in_state;
use crate::{ChannelId, ContractId, ContractSignerProvider};
use bdk_macros::maybe_await;
use bitcoin::absolute::Height;
use bitcoin::consensus::encode::serialize_hex;
use bitcoin::consensus::Decodable;
Expand Down Expand Up @@ -269,16 +270,14 @@ where
/// and an OfferDlc message returned.
///
/// This function will fetch the oracle announcements from the oracle.
#[bdk_macros::maybe_async]
pub fn send_offer(
&self,
contract_input: &ContractInput,
counter_party: PublicKey,
) -> Result<OfferDlc, Error> {
let oracle_announcements = contract_input
.contract_infos
.iter()
.map(|x| self.get_oracle_announcements(&x.oracles))
.collect::<Result<Vec<_>, Error>>()?;
let oracle_announcements =
maybe_await!(self.get_oracle_announcements_from_infos(contract_input))?;

self.send_offer_with_announcements(contract_input, counter_party, oracle_announcements)
}
Expand Down Expand Up @@ -375,13 +374,14 @@ where

/// Function to call to check the state of the currently executing DLCs and
/// update them if possible.
#[bdk_macros::maybe_async]
pub fn periodic_check(&self, check_channels: bool) -> Result<(), Error> {
self.check_signed_contracts()?;
self.check_confirmed_contracts()?;
maybe_await!(self.check_confirmed_contracts())?;
self.check_preclosed_contracts()?;

if check_channels {
self.channel_checks()?;
maybe_await!(self.channel_checks())?;
}

Ok(())
Expand Down Expand Up @@ -470,6 +470,7 @@ where
Ok(())
}

#[bdk_macros::maybe_async]
fn get_oracle_announcements(
&self,
oracle_inputs: &OracleInput,
Expand All @@ -480,7 +481,8 @@ where
.oracles
.get(pubkey)
.ok_or_else(|| Error::InvalidParameters("Unknown oracle public key".to_string()))?;
announcements.push(oracle.get_announcement(&oracle_inputs.event_id)?.clone());
let announcement = maybe_await!(oracle.get_announcement(&oracle_inputs.event_id))?;
announcements.push(announcement);
}

Ok(announcements)
Expand Down Expand Up @@ -547,13 +549,14 @@ where
Ok(())
}

#[bdk_macros::maybe_async]
fn check_confirmed_contracts(&self) -> Result<(), Error> {
for c in self.store.get_confirmed_contracts()? {
// Confirmed contracts from channel are processed in channel specific methods.
if c.channel_id.is_some() {
continue;
}
if let Err(e) = self.check_confirmed_contract(&c) {
if let Err(e) = bdk_macros::maybe_await!(self.check_confirmed_contract(&c)) {
error!(
"Error checking confirmed contract {}: {}",
c.accepted_contract.get_contract_id_string(),
Expand All @@ -565,6 +568,7 @@ where
Ok(())
}

#[bdk_macros::maybe_async]
fn get_closable_contract_info<'a>(
&'a self,
contract: &'a SignedContract,
Expand All @@ -580,19 +584,17 @@ where
})
.enumerate()
.collect();

if matured.len() >= contract_info.threshold {
let attestations: Vec<_> = matured
.iter()
.filter_map(|(i, announcement)| {
let oracle = self.oracles.get(&announcement.oracle_public_key)?;
Some((
*i,
oracle
.get_attestation(&announcement.oracle_event.event_id)
.ok()?,
))
})
.collect();
let mut attestations = Vec::new();
for (i, announcement) in matured {
let oracle = self.oracles.get(&announcement.oracle_public_key)?;
let attestation =
maybe_await!(oracle.get_attestation(&announcement.oracle_event.event_id));
if let Ok(att) = attestation {
attestations.push((i, att));
}
}
if attestations.len() >= contract_info.threshold {
return Some((contract_info, adaptor_info, attestations));
}
Expand All @@ -601,8 +603,10 @@ where
None
}

#[bdk_macros::maybe_async]
fn check_confirmed_contract(&self, contract: &SignedContract) -> Result<(), Error> {
let closable_contract_info = self.get_closable_contract_info(contract);
let closable_contract_info =
bdk_macros::maybe_await!(self.get_closable_contract_info(contract));
if let Some((contract_info, adaptor_info, attestations)) = closable_contract_info {
let offer = &contract.accepted_contract.offered_contract;
let signer = self.signer_provider.derive_contract_signer(offer.keys_id)?;
Expand Down Expand Up @@ -887,6 +891,20 @@ where

Ok(contract)
}

#[bdk_macros::maybe_async]
fn get_oracle_announcements_from_infos(
&self,
contract_input: &ContractInput,
) -> Result<Vec<Vec<OracleAnnouncement>>, Error> {
let mut oracle_announcements = vec![];
for contract_info in contract_input.contract_infos.clone() {
let announcement = maybe_await!(self.get_oracle_announcements(&contract_info.oracles))?;
oracle_announcements.push(announcement);
}

Ok(oracle_announcements)
}
}

impl<W: Deref, SP: Deref, B: Deref, S: Deref, O: Deref, T: Deref, F: Deref, X: ContractSigner>
Expand All @@ -902,16 +920,14 @@ where
{
/// Create a new channel offer and return the [`dlc_messages::channel::OfferChannel`]
/// message to be sent to the `counter_party`.
#[bdk_macros::maybe_async]
pub fn offer_channel(
&self,
contract_input: &ContractInput,
counter_party: PublicKey,
) -> Result<OfferChannel, Error> {
let oracle_announcements = contract_input
.contract_infos
.iter()
.map(|x| self.get_oracle_announcements(&x.oracles))
.collect::<Result<Vec<_>, Error>>()?;
let oracle_announcements =
maybe_await!(self.get_oracle_announcements_from_infos(contract_input))?;

let (offered_channel, offered_contract) = crate::channel_updater::offer_channel(
&self.secp,
Expand Down Expand Up @@ -1084,6 +1100,7 @@ where
/// Returns a [`RenewOffer`] message as well as the [`PublicKey`] of the
/// counter party's node to offer the establishment of a new contract in the
/// channel.
#[bdk_macros::maybe_async]
pub fn renew_offer(
&self,
channel_id: &ChannelId,
Expand All @@ -1093,11 +1110,8 @@ where
let mut signed_channel =
get_channel_in_state!(self, channel_id, Signed, None as Option<PublicKey>)?;

let oracle_announcements = contract_input
.contract_infos
.iter()
.map(|x| self.get_oracle_announcements(&x.oracles))
.collect::<Result<Vec<_>, Error>>()?;
let oracle_announcements =
maybe_await!(self.get_oracle_announcements_from_infos(contract_input))?;

let (msg, offered_contract) = crate::channel_updater::renew_offer(
&self.secp,
Expand Down Expand Up @@ -1292,6 +1306,7 @@ where
Ok(())
}

#[bdk_macros::maybe_async]
fn try_finalize_closing_established_channel(
&self,
signed_channel: SignedChannel,
Expand All @@ -1317,11 +1332,12 @@ where
let confirmed_contract =
get_contract_in_state!(self, &contract_id, Confirmed, None as Option<PublicKey>)?;

let (contract_info, adaptor_info, attestations) = self
.get_closable_contract_info(&confirmed_contract)
.ok_or_else(|| {
Error::InvalidState("Could not get information to close contract".to_string())
})?;
let (contract_info, adaptor_info, attestations) = maybe_await!(
self.get_closable_contract_info(&confirmed_contract)
)
.ok_or_else(|| {
Error::InvalidState("Could not get information to close contract".to_string())
})?;

let (signed_cet, closed_channel) =
crate::channel_updater::finalize_unilateral_close_settled_channel(
Expand Down Expand Up @@ -2079,13 +2095,14 @@ where
Ok(())
}

#[bdk_macros::maybe_async]
fn channel_checks(&self) -> Result<(), Error> {
let established_closing_channels = self
.store
.get_signed_channels(Some(SignedChannelStateType::Closing))?;

for channel in established_closing_channels {
if let Err(e) = self.try_finalize_closing_established_channel(channel) {
if let Err(e) = maybe_await!(self.try_finalize_closing_established_channel(channel)) {
error!("Error trying to close established channel: {}", e);
}
}
Expand Down

0 comments on commit ad64fea

Please sign in to comment.