/*
* HTLC (Hash Time-Locked Contract)
*
* The recipient can spend the coins by providing the secret preimage of a hash.
* The sender can cancel the transfer after a fixed block height.
*
* HTLCs enable two-way payment channels and multi-hop payments,
* such as on the Lightning network.
*
* https://docs.ivylang.org/bitcoin/language/ExampleContracts.html#htlc
*/
fn sha2(string: u256) -> u256 {
let hasher: Ctx8 = jet::sha_256_ctx_8_init();
let hasher: Ctx8 = jet::sha_256_ctx_8_add_32(hasher, string);
jet::sha_256_ctx_8_finalize(hasher)
}
fn checksig(pk: Pubkey, sig: Signature) {
let msg: u256 = jet::sig_all_hash();
jet::bip_0340_verify((pk, msg), sig);
}
fn complete_spend(preimage: u256, recipient_sig: Signature) {
let hash: u256 = sha2(preimage);
let expected_hash: u256 = 0x66687aadf862bd776c8fc18b8e9f8e20089714856ee233b3902a591d0d5f2925; // sha2([0x00; 32])
assert!(jet::eq_256(hash, expected_hash));
let recipient_pk: Pubkey = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798; // 1 * G
checksig(recipient_pk, recipient_sig);
}
fn cancel_spend(sender_sig: Signature) {
let timeout: Height = 1000;
jet::check_lock_height(timeout);
let sender_pk: Pubkey = 0xc6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5; // 2 * G
checksig(sender_pk, sender_sig)
}
fn main() {
match witness::COMPLETE_OR_CANCEL {
Left(preimage_sig: (u256, Signature)) => {
let (preimage, recipient_sig): (u256, Signature) = preimage_sig;
complete_spend(preimage, recipient_sig);
},
Right(sender_sig: Signature) => cancel_spend(sender_sig),
}
}