Skip to content

Commit

Permalink
cch: use wrapped btc in SendBTC order
Browse files Browse the repository at this point in the history
  • Loading branch information
doitian committed Jun 17, 2024
1 parent 62f7e5b commit 444fb6e
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 109 deletions.
86 changes: 43 additions & 43 deletions src/cch/actor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use std::time::{Duration, SystemTime, UNIX_EPOCH};
use tokio::{select, time::sleep};
use tokio_util::{sync::CancellationToken, task::TaskTracker};

use crate::ckb_chain::contracts::{get_script_by_contract, Contract};
use crate::invoice::Currency;

use super::error::CchDbError;
Expand Down Expand Up @@ -280,31 +281,35 @@ impl CchActor {

let amount_msat = invoice
.amount_milli_satoshis()
.ok_or(CchError::BTCInvoiceMissingAmount)?;

log::debug!("SendBTC expiry: {:?}", expiry);
let (ratio_ckb_shannons, ratio_btc_msat) =
match (self.config.ratio_ckb_shannons, self.config.ratio_btc_msat) {
(Some(ratio_ckb_shannons), Some(ratio_btc_msat)) => {
(ratio_ckb_shannons, ratio_btc_msat)
}
_ => return Err(CchError::CKBAssetNotAllowed.into()),
};
let order_value = ((ratio_ckb_shannons as u128) * (amount_msat as u128)
/ (ratio_btc_msat as u128)) as u64;
let fee = order_value * self.config.fee_rate_per_million_shannons / 1_000_000
+ self.config.base_fee_shannons;

.ok_or(CchError::BTCInvoiceMissingAmount)? as u128;

let fee = amount_msat * (self.config.fee_rate_per_million_sats as u128)
/ 1_000_000_000_000u128
+ (self.config.base_fee_sats as u128);

let wrapped_btc_type_script: ckb_jsonrpc_types::Script = get_script_by_contract(
Contract::SimpleUDT,
hex::decode(
&self
.config
.wrapped_btc_type_script_args
.trim_start_matches("0x"),
)
.map_err(|_| CchError::HexDecodingError)?
.as_ref(),
)
.into();
let mut order = SendBTCOrder {
expiry,
wrapped_btc_type_script,
currency: send_btc.currency,
timestamp: duration_since_epoch.as_secs(),
ckb_final_tlc_expiry: self.config.ckb_final_tlc_expiry,
btc_pay_req: send_btc.btc_pay_req,
ckb_pay_req: Default::default(),
payment_hash: invoice.payment_hash().encode_hex(),
payment_preimage: None,
amount_shannons: order_value + fee,
amount_sats: amount_msat / 1_000_000u128 + fee,
status: CchOrderStatus::Pending,
};
order.generate_ckb_invoice()?;
Expand Down Expand Up @@ -362,26 +367,18 @@ impl CchActor {

async fn receive_btc(
&self,
myself: ActorRef<CchMessage>,
_myself: ActorRef<CchMessage>,
state: &mut CchState,
receive_btc: ReceiveBTC,
) -> Result<()> {
let duration_since_epoch = SystemTime::now().duration_since(UNIX_EPOCH)?;
let hash_bin = hex::decode(&receive_btc.payment_hash)?;

let (ratio_ckb_shannons, ratio_btc_msat) =
match (self.config.ratio_ckb_shannons, self.config.ratio_btc_msat) {
(Some(ratio_ckb_shannons), Some(ratio_btc_msat)) => {
(ratio_ckb_shannons, ratio_btc_msat)
}
_ => return Err(CchError::CKBAssetNotAllowed.into()),
};
let order_value = ((ratio_ckb_shannons as u128) * (receive_btc.amount_msat as u128)
/ (ratio_btc_msat as u128)) as u64;
let fee = order_value * self.config.fee_rate_per_million_shannons / 1_000_000
+ self.config.base_fee_shannons;
// TODO: check that the amount is larger than the minimal allowed CKB payment.
let amount_shannons = order_value
let order_value = receive_btc.amount_msat as u128;
let fee = order_value * (self.config.fee_rate_per_million_sats as u128)
/ 1_000_000_000_000u128
+ (self.config.base_fee_sats as u128);
let amount_sats = (order_value / 1_000_000u128)
.checked_sub(fee)
.ok_or(CchError::ReceiveBTCOrderAmountTooSmall)?;

Expand All @@ -396,31 +393,34 @@ impl CchActor {
let invoice = client.add_hold_invoice(req).await?.into_inner();
let btc_pay_req = invoice.payment_request;

let order = ReceiveBTCOrder {
let _order = ReceiveBTCOrder {
timestamp: duration_since_epoch.as_secs(),
expiry: DEFAULT_ORDER_EXPIRY_SECONDS,
ckb_final_tlc_expiry: receive_btc.final_tlc_expiry,
btc_pay_req,
payment_hash: receive_btc.payment_hash.clone(),
payment_preimage: None,
amount_shannons,
amount_sats,
// TODO: check whether this node has the peer with this pubkey.
payee_pubkey: receive_btc.payee_pubkey,
status: CchOrderStatus::Pending,
currency: todo!(),
wrapped_btc_type_script: todo!(),
ckb_pay_req: todo!(),
};

// TODO(cch): Return it as the RPC response
log::info!("ReceiveBTCOrder: {}", serde_json::to_string(&order)?);
state.orders_db.insert_receive_btc_order(order).await?;

let invoice_tracker = LndInvoiceTracker::new(
myself,
receive_btc.payment_hash,
state.lnd_connection.clone(),
self.token.clone(),
);
self.tracker
.spawn(async move { invoice_tracker.run().await });
// log::info!("ReceiveBTCOrder: {}", serde_json::to_string(&order)?);
// state.orders_db.insert_receive_btc_order(order).await?;

// let invoice_tracker = LndInvoiceTracker::new(
// myself,
// receive_btc.payment_hash,
// state.lnd_connection.clone(),
// self.token.clone(),
// );
// self.tracker
// .spawn(async move { invoice_tracker.run().await });

Ok(())
}
Expand Down
30 changes: 12 additions & 18 deletions src/cch/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,20 +48,14 @@ pub struct CchConfig {
)]
pub lnd_macaroon_path: Option<String>,

// TODO: use hex type
#[arg(
name = "CCH_RATIO_BTC_MSAT",
long = "cch-ratio-btc-msat",
name = "CCH_WRAPPED_BTC_TYPE_SCRIPT_ARGS",
long = "cch-wrapped-btc-type-script-args",
env,
help = "exchange ratio between BTC and CKB, in milisatoshi per `CCH_RATIO_CKB_SHANNONS` shannon"
help = "Wrapped BTC type script args. It must be a UDT with 8 decimal places."
)]
pub ratio_btc_msat: Option<u64>,
#[arg(
name = "CCH_RATIO_CKB_SHANNONS",
long = "cch-ratio-ckb-shannons",
env,
help = "exchange ratio between BTC and CKB, in shannons per `CCH_RATIO_BTC_MSAT` shannon"
)]
pub ratio_ckb_shannons: Option<u64>,
pub wrapped_btc_type_script_args: String,

/// Cross-chain order expiry time in seconds.
#[default(DEFAULT_ORDER_EXPIRY_TIME)]
Expand All @@ -75,21 +69,21 @@ pub struct CchConfig {

#[default(0)]
#[arg(
name = "CCH_BASE_FEE_SHANNONS",
long = "cch-base-fee-shannons",
name = "CCH_BASE_FEE_SATS",
long = "cch-base-fee-sats",
env,
help = "The base fee charged for each cross-chain order, default is 0"
)]
pub base_fee_shannons: u64,
pub base_fee_sats: u64,

#[default(1)]
#[arg(
name = "CCH_FEE_RATE_PER_MILLION_SHANNONS",
long = "cch-fee-rate-per-million-shannons",
name = "CCH_FEE_RATE_PER_MILLION_SATS",
long = "cch-fee-rate-per-million-sats",
env,
help = "The proportional fee charged per million shannons based on the cross-chain order value, default is 1"
help = "The proportional fee charged per million satoshis based on the cross-chain order value, default is 1"
)]
pub fee_rate_per_million_shannons: u64,
pub fee_rate_per_million_sats: u64,

/// Final tlc expiry time for BTC network.
#[default(DEFAULT_BTC_FINAL_TLC_EXPIRY_TIME)]
Expand Down
19 changes: 12 additions & 7 deletions src/cch/order.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,29 +56,31 @@ pub struct SendBTCOrder {
pub expiry: u64,
// The minimal expiry in seconds of the final TLC in the CKB network
pub ckb_final_tlc_expiry: u64,

pub currency: Currency,
pub wrapped_btc_type_script: ckb_jsonrpc_types::Script,

pub btc_pay_req: String,
pub ckb_pay_req: String,
pub payment_hash: String,
pub payment_preimage: Option<String>,

// Amount required to pay in Shannons
pub amount_shannons: u64,
// Amount required to pay in Satoshis
pub amount_sats: u128,

pub status: CchOrderStatus,
}

impl SendBTCOrder {
pub fn generate_ckb_invoice(&mut self) -> Result<(), CchError> {
let invoice_builder = InvoiceBuilder::new(self.currency)
.amount(Some(self.amount_shannons as u128))
.amount(Some(self.amount_sats))
.payment_hash(
Hash256::from_str(&self.payment_hash).map_err(|_| CchError::HexDecodingError)?,
)
.expiry_time(Duration::from_secs(self.expiry))
.final_cltv(self.ckb_final_tlc_expiry);
// TODO(now): udt order: invoice_builder.udt_type_script(udt_type_script.clone().into());
.final_cltv(self.ckb_final_tlc_expiry)
.udt_type_script(self.wrapped_btc_type_script.clone().into());

let invoice = invoice_builder.build()?;
self.ckb_pay_req = invoice.to_string();
Expand All @@ -96,13 +98,16 @@ pub struct ReceiveBTCOrder {
// The minimal expiry in seconds of the final TLC in the CKB network
pub ckb_final_tlc_expiry: u64,

// Generated invoice
pub currency: Currency,
pub wrapped_btc_type_script: ckb_jsonrpc_types::Script,

pub btc_pay_req: String,
pub ckb_pay_req: String,
pub payment_hash: String,
pub payment_preimage: Option<String>,

// Amount will be received by the payee
pub amount_shannons: u64,
pub amount_sats: u128,
// Payee in the CKB network
pub payee_pubkey: String,

Expand Down
9 changes: 0 additions & 9 deletions tests/nodes/1/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,6 @@ ckb:
rpc:
listening_addr: 127.0.0.1:41714

ckb_chain:
# sighash_all
funding_source_lock_script_code_hash: "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8"
funding_source_lock_script_hash_type: "type"

# funding lock
funding_cell_lock_script_code_hash: "0x8090ce20be9976e2407511502acebf74ac1cfed10d7b35b7f33f56c9bd0daec6"
funding_cell_lock_script_hash_type: "type"

services:
- ckb
- rpc
Expand Down
9 changes: 0 additions & 9 deletions tests/nodes/2/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,6 @@ ckb:
rpc:
listening_addr: 127.0.0.1:41715

ckb_chain:
# sighash_all
funding_source_lock_script_code_hash: "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8"
funding_source_lock_script_hash_type: "type"

# funding lock
funding_cell_lock_script_code_hash: "0x8090ce20be9976e2407511502acebf74ac1cfed10d7b35b7f33f56c9bd0daec6"
funding_cell_lock_script_hash_type: "type"

services:
- ckb
- rpc
Expand Down
14 changes: 1 addition & 13 deletions tests/nodes/3/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,9 @@ rpc:
listening_addr: 127.0.0.1:41716

cch:
ratio_btc_msat: 1
ratio_ckb_shannons: 5000
allow_expired_btc_invoice: true
wrapped_btc_type_script_args: "0x32e555f3ff8e135cece1351a6a2971518392c1e30375c1e006ad0ce8eac07947"
lnd_cert_path: ../../../deploy/lnd-init/lnd-ingrid/tls.cert

# Note that we are different in the sense we have 20 billions of CKB tokens in the genesis block.
ckb_chain:
# sighash_all
funding_source_lock_script_code_hash: "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8"
funding_source_lock_script_hash_type: "type"

# funding lock
funding_cell_lock_script_code_hash: "0x8090ce20be9976e2407511502acebf74ac1cfed10d7b35b7f33f56c9bd0daec6"
funding_cell_lock_script_hash_type: "type"

services:
- ckb
- cch
Expand Down
10 changes: 0 additions & 10 deletions tests/nodes/deployer/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,6 @@ cch:
ratio_ckb_shannons: 5000
allow_expired_btc_invoice: true

# Note that we are different in the sense we have 20 billions of CKB tokens in the genesis block.
ckb_chain:
# sighash_all
funding_source_lock_script_code_hash: "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8"
funding_source_lock_script_hash_type: "type"

# funding lock
funding_cell_lock_script_code_hash: "0x8090ce20be9976e2407511502acebf74ac1cfed10d7b35b7f33f56c9bd0daec6"
funding_cell_lock_script_hash_type: "type"

services:
- ckb
- cch
Expand Down

0 comments on commit 444fb6e

Please sign in to comment.