Skip to content

Commit

Permalink
Implement ordinal support
Browse files Browse the repository at this point in the history
  • Loading branch information
Tibo-lg committed Oct 31, 2023
1 parent 4d49b0d commit ec82297
Show file tree
Hide file tree
Showing 28 changed files with 3,092 additions and 210 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ jobs:
key: test-cache-${{ github.run_id }}-${{ github.run_number }}
- uses: actions/checkout@v2
- id: set-matrix
run: cargo test --no-run && echo "::set-output name=matrix::$(scripts/get_test_list.sh execution manager channel_execution)"
run: cargo test --no-run && echo "::set-output name=matrix::$(scripts/get_test_list.sh execution manager channel_execution ordinals)"
integration_tests:
name: integration-tests
needs: integration_tests_prepare
Expand Down
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
[workspace]

resolver = "2"

members = [
"bitcoin-test-utils",
"bitcoin-rpc-provider",
Expand Down
99 changes: 97 additions & 2 deletions dlc-manager/src/contract/contract_info.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! #ContractInfo

use super::ord_descriptor::OrdOutcomeDescriptor;
use super::AdaptorInfo;
use super::ContractDescriptor;
use crate::error::Error;
Expand Down Expand Up @@ -37,6 +38,9 @@ impl ContractInfo {
match &self.contract_descriptor {
ContractDescriptor::Enum(e) => Ok(e.get_payouts()),
ContractDescriptor::Numerical(n) => n.get_payouts(total_collateral),
ContractDescriptor::Ord(_) => Err(Error::InvalidState(
"Should not call this method for Ord contracts".to_string(),
)),
}
}

Expand Down Expand Up @@ -81,7 +85,21 @@ impl ContractInfo {
funding_script_pubkey,
fund_output_value,
),
_ => unreachable!(),
ContractDescriptor::Ord(o) => match &o.outcome_descriptor {
super::ord_descriptor::OrdOutcomeDescriptor::Enum(e) => {
e.descriptor.get_adaptor_signatures(
secp,
&self.get_oracle_infos(),
self.threshold,
cets,
fund_privkey,
funding_script_pubkey,
fund_output_value,
)
}
super::ord_descriptor::OrdOutcomeDescriptor::Numerical(_) => unreachable!(),
},
ContractDescriptor::Numerical(_) => unreachable!(),
},
AdaptorInfo::Numerical(trie) => Ok(trie.sign(
secp,
Expand Down Expand Up @@ -140,6 +158,33 @@ impl ContractInfo {
adaptor_sigs,
adaptor_sig_start,
)?),
ContractDescriptor::Ord(o) => match &o.outcome_descriptor {
OrdOutcomeDescriptor::Enum(e) => Ok(e.descriptor.verify_and_get_adaptor_info(
secp,
&oracle_infos,
self.threshold,
fund_pubkey,
funding_script_pubkey,
fund_output_value,
cets,
adaptor_sigs,
adaptor_sig_start,
)?),
OrdOutcomeDescriptor::Numerical(n) => {
Ok(n.descriptor.verify_and_get_adaptor_info_internal(
secp,
&n.get_range_payouts(total_collateral)?,
fund_pubkey,
funding_script_pubkey,
fund_output_value,
self.threshold,
&self.precompute_points(secp)?,
cets,
adaptor_sigs,
adaptor_sig_start,
)?)
}
},
}
}

Expand All @@ -158,6 +203,15 @@ impl ContractInfo {
outcomes,
adaptor_sig_start,
),
ContractDescriptor::Ord(o) => match &o.outcome_descriptor {
OrdOutcomeDescriptor::Enum(e) => e.descriptor.get_range_info_for_outcome(
self.oracle_announcements.len(),
self.threshold,
outcomes,
adaptor_sig_start,
),
OrdOutcomeDescriptor::Numerical(_) => unreachable!(),
},
_ => unreachable!(),
},
AdaptorInfo::Numerical(n) => {
Expand Down Expand Up @@ -204,7 +258,26 @@ impl ContractInfo {
adaptor_sigs,
adaptor_sig_start,
)?),
ContractDescriptor::Numerical(_) => match adaptor_info {
ContractDescriptor::Ord(o)
if matches!(&o.outcome_descriptor, OrdOutcomeDescriptor::Enum(_)) =>
{
if let OrdOutcomeDescriptor::Enum(e) = &o.outcome_descriptor {
Ok(e.descriptor.verify_adaptor_info(
secp,
&oracle_infos,
self.threshold,
fund_pubkey,
funding_script_pubkey,
fund_output_value,
cets,
adaptor_sigs,
adaptor_sig_start,
)?)
} else {
unreachable!()
}
}
_ => match adaptor_info {
AdaptorInfo::Enum => unreachable!(),
AdaptorInfo::Numerical(trie) => Ok(trie.verify(
secp,
Expand Down Expand Up @@ -263,6 +336,28 @@ impl ContractInfo {
cets,
adaptor_index_start,
)?),
ContractDescriptor::Ord(o) => match &o.outcome_descriptor {
OrdOutcomeDescriptor::Enum(e) => Ok(e.descriptor.get_adaptor_info(
secp,
&self.get_oracle_infos(),
self.threshold,
fund_priv_key,
funding_script_pubkey,
fund_output_value,
cets,
)?),
OrdOutcomeDescriptor::Numerical(n) => Ok(n.descriptor.get_adaptor_info_internal(
secp,
&n.get_range_payouts(total_collateral)?,
fund_priv_key,
funding_script_pubkey,
fund_output_value,
self.threshold,
&self.precompute_points(secp)?,
cets,
adaptor_index_start,
)?),
},
}
}

Expand Down
29 changes: 24 additions & 5 deletions dlc-manager/src/contract/enum_descriptor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use super::utils::{get_majority_combination, unordered_equal};
use super::AdaptorInfo;
use crate::error::Error;
use bitcoin::{Script, Transaction};
use dlc::OracleInfo;
use dlc::{DlcTransactions, OracleInfo, PartyParams};
use dlc::{EnumerationPayout, Payout};
use dlc_messages::oracle_msgs::EnumEventDescriptor;
use dlc_trie::{combination_iterator::CombinationIterator, RangeInfo};
Expand All @@ -30,10 +30,7 @@ pub struct EnumDescriptor {
impl EnumDescriptor {
/// Returns the set of payouts.
pub fn get_payouts(&self) -> Vec<Payout> {
self.outcome_payouts
.iter()
.map(|x| x.payout.clone())
.collect()
self.outcome_payouts.iter().map(|x| x.payout).collect()
}

/// Validate that the descriptor covers all possible outcomes of the given
Expand Down Expand Up @@ -273,4 +270,26 @@ impl EnumDescriptor {

Ok(())
}

pub(crate) fn create_dlc_transactions(
&self,
offer_params: &PartyParams,
accept_params: &PartyParams,
refund_locktime: u32,
fee_rate_per_vb: u64,
fund_locktime: u32,
cet_locktime: u32,
fund_output_serial_id: u64,
) -> Result<DlcTransactions, Error> {
crate::utils::create_dlc_transactions_from_payouts(
offer_params,
accept_params,
&self.get_payouts(),
refund_locktime,
fee_rate_per_vb,
fund_locktime,
cet_locktime,
fund_output_serial_id,
)
}
}
57 changes: 55 additions & 2 deletions dlc-manager/src/contract/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub mod contract_input;
pub mod enum_descriptor;
pub mod numerical_descriptor;
pub mod offered_contract;
pub mod ord_descriptor;
pub mod ser;
pub mod signed_contract;
pub(crate) mod utils;
Expand Down Expand Up @@ -211,6 +212,8 @@ pub enum ContractDescriptor {
Enum(enum_descriptor::EnumDescriptor),
/// Case for numerical outcome DLC.
Numerical(numerical_descriptor::NumericalDescriptor),
/// Case for a contract involving an ordinal.
Ord(ord_descriptor::OrdDescriptor),
}

impl ContractDescriptor {
Expand All @@ -219,6 +222,7 @@ impl ContractDescriptor {
match self {
ContractDescriptor::Enum(_) => None,
ContractDescriptor::Numerical(n) => n.difference_params.clone(),
ContractDescriptor::Ord(_) => None,
}
}

Expand All @@ -242,7 +246,7 @@ impl ContractDescriptor {
));
}
}
_ => {
EventDescriptor::DigitDecompositionEvent(_) => {
return Err(Error::InvalidParameters(
"Expected enum event descriptor.".to_string(),
))
Expand All @@ -251,9 +255,24 @@ impl ContractDescriptor {
}
match self {
ContractDescriptor::Enum(ed) => ed.validate(ee),
_ => Err(Error::InvalidParameters(
ContractDescriptor::Numerical(_) => Err(Error::InvalidParameters(
"Event descriptor from contract and oracle differ.".to_string(),
)),
ContractDescriptor::Ord(ord_desc) => {
match &ord_desc.outcome_descriptor {
ord_descriptor::OrdOutcomeDescriptor::Enum(e) => {
if e.to_offer_payouts.len() != e.descriptor.outcome_payouts.len() {
return Err(Error::InvalidParameters("Ordinal to offer list length differ from outcome list length.".to_string()));
}
e.descriptor.validate(ee)
}
ord_descriptor::OrdOutcomeDescriptor::Numerical(_) => {
Err(Error::InvalidParameters(
"Event descriptor from contract and oracle differ.".to_string(),
))
}
}
}
}
}
EventDescriptor::DigitDecompositionEvent(_) => match self {
Expand All @@ -268,6 +287,40 @@ impl ContractDescriptor {
})?;
n.validate((max_value - 1) as u64)
}
ContractDescriptor::Ord(ord_desc) => match &ord_desc.outcome_descriptor {
ord_descriptor::OrdOutcomeDescriptor::Numerical(n) => {
let min_nb_digits = n.descriptor.oracle_numeric_infos.get_min_nb_digits();
let max_value = n
.descriptor
.oracle_numeric_infos
.base
.checked_pow(min_nb_digits as u32)
.ok_or_else(|| {
Error::InvalidParameters("Could not compute max value".to_string())
})?;

for i in 0..n.to_offer_ranges.len() {
if n.to_offer_ranges[i].0 > n.to_offer_ranges[i].1 {
return Err(Error::InvalidParameters(
"Invalid range, start greater than end".to_string(),
));
}
if i > 0 && n.to_offer_ranges[i - 1].1 >= n.to_offer_ranges[i].0 {
return Err(Error::InvalidParameters(
"Consecutive to offer ranges should not overlap.".to_string(),
));
}

if n.to_offer_ranges[i].1 as usize > max_value - 1 {
return Err(Error::InvalidParameters("To offer range end is greater than maximum value for the event.".to_string()));
}
}
n.descriptor.validate((max_value - 1) as u64)
}
ord_descriptor::OrdOutcomeDescriptor::Enum(_) => Err(Error::InvalidParameters(
"Event descriptor from contract and oracle differ.".to_string(),
)),
},
_ => Err(Error::InvalidParameters(
"Event descriptor from contract and oracle differ.".to_string(),
)),
Expand Down
Loading

0 comments on commit ec82297

Please sign in to comment.