Skip to content

Commit

Permalink
Merge pull request #5 from quake/quake/xudt-comp
Browse files Browse the repository at this point in the history
fix: try to resolve xudt compatibility issue
  • Loading branch information
quake authored Jun 23, 2024
2 parents c8b1140 + 04dcdaf commit 21c70cc
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 16 deletions.
1 change: 1 addition & 0 deletions contracts/commitment-lock/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ This is a simple commitment lock script for ckb fiber network.

The lock script args is the hash result of blake160(local_delay_epoch || local_delay_pubkey_hash || revocation_pubkey_hash || N * pending_htlc), to unlock this lock, the transaction must provide following fields in the witness:

- `empty_witness_args`: 16 bytes, fixed to 0x10000000100000001000000010000000, for compatibility with the xudt
- `local_delay_epoch`: 8 bytes, u64 in little endian, must be a relative EpochNumberWithFraction
- `local_delay_pubkey_hash`: 20 bytes, hash result of blake160(local_delay_pubkey)
- `revocation_pubkey_hash`: 20 bytes, hash result of blake160(revocation_pubkey)
Expand Down
12 changes: 11 additions & 1 deletion contracts/commitment-lock/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ pub enum Error {
InvalidHtlcType,
ArgsLenError,
WitnessLenError,
EmptyWitnessArgsError,
WitnessHashError,
OutputCapacityError,
OutputLockError,
Expand Down Expand Up @@ -68,6 +69,8 @@ pub fn program_entry() -> i8 {
}
}

// a placeholder for empty witness args, to resolve the issue of xudt compatibility
const EMPTY_WITNESS_ARGS: [u8; 16] = [16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0];
// min witness script length: 8 (local_delay_epoch) + 20 (local_delay_pubkey_hash) + 20 (revocation_pubkey_hash) = 48
const MIN_WITNESS_SCRIPT_LEN: usize = 48;
// HTLC script length: 1 (htlc_type) + 16 (payment_amount) + 20 (payment_hash) + 20 (remote_htlc_pubkey_hash) + 20 (local_htlc_pubkey_hash) + 8 (htlc_expiry) = 85
Expand Down Expand Up @@ -120,7 +123,14 @@ fn auth() -> Result<(), Error> {
if args.len() != 20 {
return Err(Error::ArgsLenError);
}
let witness = load_witness(0, Source::GroupInput)?;
let mut witness = load_witness(0, Source::GroupInput)?;
if witness
.drain(0..EMPTY_WITNESS_ARGS.len())
.collect::<Vec<_>>()
!= EMPTY_WITNESS_ARGS
{
return Err(Error::EmptyWitnessArgsError);
}
let witness_len = witness.len();
if witness_len < MIN_WITNESS_LEN {
return Err(Error::WitnessLenError);
Expand Down
1 change: 1 addition & 0 deletions contracts/funding-lock/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ This is a simple funding lock script for ckb fiber network. It utilizes the [ckb

The lock script args is a blake160 hash of the aggregated public key of the two parties, to unlock this lock, the transaction must provide following fields in the witness:

- `empty_witness_args`: 16 bytes, fixed to 0x10000000100000001000000010000000, for compatibility with the xudt
- `version`: 8 bytes, u64 in little-endian
- `funding_out_point`: 36 bytes, out point of the funding transaction
- `pubkey`: 32 bytes, x only aggregated public key
Expand Down
15 changes: 13 additions & 2 deletions contracts/funding-lock/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ ckb_std::entry!(program_entry);
#[cfg(not(test))]
default_alloc!();

use alloc::ffi::CString;
use alloc::{ffi::CString, vec::Vec};
use ckb_std::{
ckb_constants::Source,
ckb_types::{bytes::Bytes, core::ScriptHashType, prelude::*},
Expand All @@ -34,6 +34,7 @@ pub enum Error {
// Add customized errors here...
MultipleInputs,
WitnessLenError,
EmptyWitnessArgsError,
FundingOutPointError,
AuthError,
}
Expand All @@ -57,12 +58,22 @@ pub fn program_entry() -> i8 {
}
}

// a placeholder for empty witness args, to resolve the issue of xudt compatibility
const EMPTY_WITNESS_ARGS: [u8; 16] = [16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0];

fn auth() -> Result<(), Error> {
// funding lock will be unlocked by the commitment transaction, it should only have one input
if load_input_since(1, Source::GroupInput).is_ok() {
return Err(Error::MultipleInputs);
}
let witness = load_witness(0, Source::GroupInput)?;
let mut witness = load_witness(0, Source::GroupInput)?;
if witness
.drain(0..EMPTY_WITNESS_ARGS.len())
.collect::<Vec<_>>()
!= EMPTY_WITNESS_ARGS
{
return Err(Error::EmptyWitnessArgsError);
}
if witness.len() != 8 + 36 + 32 + 64 {
return Err(Error::WitnessLenError);
}
Expand Down
106 changes: 93 additions & 13 deletions tests/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ use secp256k1::{
};

const MAX_CYCLES: u64 = 10_000_000;

const BYTE_SHANNONS: u64 = 100_000_000;
const EMPTY_WITNESS_ARGS: [u8; 16] = [16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0];

#[test]
fn test_funding_lock() {
Expand Down Expand Up @@ -152,6 +152,7 @@ fn test_funding_lock() {
println!("signature: {:?}", aggregated_signature_1.to_bytes());

let witness = [
EMPTY_WITNESS_ARGS.to_vec(),
version.to_vec(),
funding_out_point.to_vec(),
x_only_pub_key.to_vec(),
Expand Down Expand Up @@ -250,7 +251,13 @@ fn test_commitment_lock_no_pending_htlcs() {
.sign_recoverable(&message.into())
.unwrap()
.serialize();
let witness = [witness_script.clone(), vec![0xFF], signature].concat();
let witness = [
EMPTY_WITNESS_ARGS.to_vec(),
witness_script.clone(),
vec![0xFF],
signature,
]
.concat();

let tx = tx.as_advanced_builder().witness(witness.pack()).build();
println!("tx: {:?}", tx);
Expand Down Expand Up @@ -284,7 +291,13 @@ fn test_commitment_lock_no_pending_htlcs() {
.sign_recoverable(&message.into())
.unwrap()
.serialize();
let witness = [witness_script, vec![0xFF], signature].concat();
let witness = [
EMPTY_WITNESS_ARGS.to_vec(),
witness_script,
vec![0xFF],
signature,
]
.concat();

let tx = tx.as_advanced_builder().witness(witness.pack()).build();
println!("tx: {:?}", tx);
Expand Down Expand Up @@ -400,7 +413,13 @@ fn test_commitment_lock_with_two_pending_htlcs() {
.sign_recoverable(&message.into())
.unwrap()
.serialize();
let witness = [witness_script.clone(), vec![0xFF], signature].concat();
let witness = [
EMPTY_WITNESS_ARGS.to_vec(),
witness_script.clone(),
vec![0xFF],
signature,
]
.concat();

let tx = tx.as_advanced_builder().witness(witness.pack()).build();
println!("tx: {:?}", tx);
Expand Down Expand Up @@ -434,7 +453,13 @@ fn test_commitment_lock_with_two_pending_htlcs() {
.sign_recoverable(&message.into())
.unwrap()
.serialize();
let witness = [witness_script.clone(), vec![0xFF], signature].concat();
let witness = [
EMPTY_WITNESS_ARGS.to_vec(),
witness_script.clone(),
vec![0xFF],
signature,
]
.concat();

let tx = tx.as_advanced_builder().witness(witness.pack()).build();
println!("tx: {:?}", tx);
Expand Down Expand Up @@ -488,6 +513,7 @@ fn test_commitment_lock_with_two_pending_htlcs() {
.unwrap()
.serialize();
let witness = [
EMPTY_WITNESS_ARGS.to_vec(),
witness_script.clone(),
vec![0x00],
signature.clone(),
Expand All @@ -503,6 +529,7 @@ fn test_commitment_lock_with_two_pending_htlcs() {

// sign with remote_htlc_pubkey and wrong preimage should fail
let witness = [
EMPTY_WITNESS_ARGS.to_vec(),
witness_script.clone(),
vec![0x00],
signature.clone(),
Expand All @@ -519,7 +546,13 @@ fn test_commitment_lock_with_two_pending_htlcs() {
println!("error: {}", error);

// sign with remote_htlc_pubkey and empty preimage should fail
let witness = [witness_script.clone(), vec![0x00], signature].concat();
let witness = [
EMPTY_WITNESS_ARGS.to_vec(),
witness_script.clone(),
vec![0x00],
signature,
]
.concat();

let fail_tx = tx.as_advanced_builder().witness(witness.pack()).build();

Expand Down Expand Up @@ -556,7 +589,13 @@ fn test_commitment_lock_with_two_pending_htlcs() {
.sign_recoverable(&message.into())
.unwrap()
.serialize();
let witness = [witness_script.clone(), vec![0x00], signature.clone()].concat();
let witness = [
EMPTY_WITNESS_ARGS.to_vec(),
witness_script.clone(),
vec![0x00],
signature.clone(),
]
.concat();

let success_tx = tx.as_advanced_builder().witness(witness.pack()).build();
let cycles = context
Expand Down Expand Up @@ -586,7 +625,13 @@ fn test_commitment_lock_with_two_pending_htlcs() {
.sign_recoverable(&message.into())
.unwrap()
.serialize();
let witness = [witness_script.clone(), vec![0x00], signature].concat();
let witness = [
EMPTY_WITNESS_ARGS.to_vec(),
witness_script.clone(),
vec![0x00],
signature,
]
.concat();

let fail_tx = tx.as_advanced_builder().witness(witness.pack()).build();
let error = context
Expand Down Expand Up @@ -637,7 +682,13 @@ fn test_commitment_lock_with_two_pending_htlcs() {
.sign_recoverable(&message.into())
.unwrap()
.serialize();
let witness = [witness_script.clone(), vec![0x01], signature].concat();
let witness = [
EMPTY_WITNESS_ARGS.to_vec(),
witness_script.clone(),
vec![0x01],
signature,
]
.concat();

let tx = tx.as_advanced_builder().witness(witness.pack()).build();
println!("tx: {:?}", tx);
Expand Down Expand Up @@ -673,6 +724,7 @@ fn test_commitment_lock_with_two_pending_htlcs() {
.unwrap()
.serialize();
let witness = [
EMPTY_WITNESS_ARGS.to_vec(),
witness_script.clone(),
vec![0x01],
signature.clone(),
Expand All @@ -688,6 +740,7 @@ fn test_commitment_lock_with_two_pending_htlcs() {

// sign with local_htlc_pubkey and wrong preimage should fail
let witness = [
EMPTY_WITNESS_ARGS.to_vec(),
witness_script.clone(),
vec![0x01],
signature.clone(),
Expand All @@ -702,7 +755,13 @@ fn test_commitment_lock_with_two_pending_htlcs() {
println!("error: {}", error);

// sign with local_htlc_pubkey and empty preimage should fail
let witness = [witness_script.clone(), vec![0x01], signature].concat();
let witness = [
EMPTY_WITNESS_ARGS.to_vec(),
witness_script.clone(),
vec![0x01],
signature,
]
.concat();

let fail_tx = tx.as_advanced_builder().witness(witness.pack()).build();
let error = context
Expand Down Expand Up @@ -828,7 +887,13 @@ fn test_commitment_lock_with_two_pending_htlcs_and_sudt() {
.sign_recoverable(&message.into())
.unwrap()
.serialize();
let witness = [witness_script.clone(), vec![0xFF], signature].concat();
let witness = [
EMPTY_WITNESS_ARGS.to_vec(),
witness_script.clone(),
vec![0xFF],
signature,
]
.concat();

let tx = tx.as_advanced_builder().witness(witness.pack()).build();
println!("tx: {:?}", tx);
Expand Down Expand Up @@ -862,7 +927,13 @@ fn test_commitment_lock_with_two_pending_htlcs_and_sudt() {
.sign_recoverable(&message.into())
.unwrap()
.serialize();
let witness = [witness_script.clone(), vec![0xFF], signature].concat();
let witness = [
EMPTY_WITNESS_ARGS.to_vec(),
witness_script.clone(),
vec![0xFF],
signature,
]
.concat();

let tx = tx.as_advanced_builder().witness(witness.pack()).build();
println!("tx: {:?}", tx);
Expand Down Expand Up @@ -920,6 +991,7 @@ fn test_commitment_lock_with_two_pending_htlcs_and_sudt() {
.unwrap()
.serialize();
let witness = [
EMPTY_WITNESS_ARGS.to_vec(),
witness_script.clone(),
vec![0x00],
signature,
Expand Down Expand Up @@ -965,6 +1037,7 @@ fn test_commitment_lock_with_two_pending_htlcs_and_sudt() {
.unwrap()
.serialize();
let witness = [
EMPTY_WITNESS_ARGS.to_vec(),
witness_script.clone(),
vec![0x00],
signature,
Expand Down Expand Up @@ -1028,7 +1101,13 @@ fn test_commitment_lock_with_two_pending_htlcs_and_sudt() {
.sign_recoverable(&message.into())
.unwrap()
.serialize();
let witness = [witness_script.clone(), vec![0x01], signature].concat();
let witness = [
EMPTY_WITNESS_ARGS.to_vec(),
witness_script.clone(),
vec![0x01],
signature,
]
.concat();

let tx = tx.as_advanced_builder().witness(witness.pack()).build();
println!("tx: {:?}", tx);
Expand Down Expand Up @@ -1065,6 +1144,7 @@ fn test_commitment_lock_with_two_pending_htlcs_and_sudt() {
.unwrap()
.serialize();
let witness = [
EMPTY_WITNESS_ARGS.to_vec(),
witness_script.clone(),
vec![0x01],
signature,
Expand Down

0 comments on commit 21c70cc

Please sign in to comment.