2024-07-25 19:12:39 +01:00
|
|
|
use std::str::FromStr;
|
|
|
|
|
|
2024-07-25 19:54:37 +01:00
|
|
|
use bdk::miniscript::{descriptor::Wsh, policy::Concrete};
|
2024-07-25 19:12:39 +01:00
|
|
|
use bitcoin::Address;
|
|
|
|
|
|
|
|
|
|
/// A hash time locked contract between two parties.
|
|
|
|
|
///
|
|
|
|
|
/// If the hash preimage of the hashlock is revealed, the value is sent to the redeem_identity.
|
|
|
|
|
///
|
|
|
|
|
/// Alternately, if the refund timelock expires, the value can be refunded to the refund_identity.
|
|
|
|
|
pub(crate) struct Htlc {
|
|
|
|
|
value: u64,
|
|
|
|
|
redeem_identity: Address,
|
|
|
|
|
hashlock: String,
|
|
|
|
|
refund_timelock: u64,
|
|
|
|
|
refund_indentiy: Address,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Htlc {
|
|
|
|
|
/// Create a new HTLC.
|
|
|
|
|
pub(crate) fn new(
|
|
|
|
|
value: u64,
|
|
|
|
|
redeem_identity: Address,
|
|
|
|
|
hashlock: String,
|
|
|
|
|
refund_timelock: u64,
|
|
|
|
|
refund_indentiy: Address,
|
|
|
|
|
) -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
value,
|
|
|
|
|
redeem_identity,
|
|
|
|
|
hashlock,
|
|
|
|
|
refund_timelock,
|
|
|
|
|
refund_indentiy,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-25 19:54:37 +01:00
|
|
|
pub(crate) fn to_miniscript_policy(&self) -> Concrete<bdk::bitcoin::PublicKey> {
|
|
|
|
|
Concrete::<bdk::bitcoin::PublicKey>::from_str(&format!(
|
2024-07-25 19:12:39 +01:00
|
|
|
"or(10@and(sha256({secret_hash}),pk({redeem_identity})),1@and(older({expiry}),pk({refund_identity})))",
|
|
|
|
|
secret_hash = self.hashlock,
|
|
|
|
|
redeem_identity = self.redeem_identity,
|
|
|
|
|
refund_identity = self.refund_indentiy,
|
|
|
|
|
expiry = self.refund_timelock
|
|
|
|
|
)).expect("Policy compilation only fails on resource limits or mixed timelocks")
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-25 19:54:37 +01:00
|
|
|
pub(crate) fn to_miniscript_descriptor(&self) -> Wsh<bdk::bitcoin::PublicKey> {
|
2024-07-25 19:12:39 +01:00
|
|
|
Wsh::new(
|
|
|
|
|
self.to_miniscript_policy()
|
|
|
|
|
.compile()
|
|
|
|
|
.expect("Policy compilation only fails on resource limits or mixed timelocks"),
|
|
|
|
|
)
|
|
|
|
|
.expect("Resource limits")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Translate the HTLC to Bitcoin op_codes.
|
|
|
|
|
pub(crate) fn to_script(&self) -> String {
|
|
|
|
|
format!(
|
|
|
|
|
"OP_IF
|
|
|
|
|
OP_SHA256
|
|
|
|
|
{}
|
|
|
|
|
OP_EQUALVERIFY
|
|
|
|
|
OP_DUP
|
|
|
|
|
OP_HASH160
|
|
|
|
|
{}
|
|
|
|
|
OP_ELSE
|
|
|
|
|
{}
|
|
|
|
|
OP_CHECKLOCKTIMEVERIFY
|
|
|
|
|
OP_DROP
|
|
|
|
|
OP_DUP
|
|
|
|
|
OP_HASH160
|
|
|
|
|
{}
|
|
|
|
|
OP_ENDIF
|
|
|
|
|
OP_EQUALVERIFY
|
|
|
|
|
OP_CHECKSIG",
|
|
|
|
|
self.hashlock, self.redeem_identity, self.refund_timelock, self.refund_indentiy
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|