Skip to content

Commit

Permalink
feat: allow sha256 for HTLC
Browse files Browse the repository at this point in the history
Allow choosing the hash algorithm when adding the HTLC output.

Related PR: nervosnetwork/fiber-scripts#6
  • Loading branch information
doitian committed Jun 27, 2024
1 parent a46d08c commit f1970c8
Show file tree
Hide file tree
Showing 10 changed files with 473 additions and 19 deletions.
29 changes: 25 additions & 4 deletions src/ckb/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ use crate::{

use super::{
config::{DEFAULT_CHANNEL_MINIMAL_CKB_AMOUNT, MIN_UDT_OCCUPIED_CAPACITY},
hash_algorithm::HashAlgorithm,
key::blake2b_hash_with_salt,
network::CFNMessageWithPeerId,
serde_utils::EntityHex,
Expand Down Expand Up @@ -103,6 +104,7 @@ pub struct AddTlcCommand {
pub preimage: Option<Hash256>,
pub payment_hash: Option<Hash256>,
pub expiry: LockTime,
pub hash_algorithm: HashAlgorithm,
}

#[derive(Debug)]
Expand Down Expand Up @@ -563,6 +565,7 @@ impl<S> ChannelActor<S> {
amount: tlc.amount,
payment_hash: tlc.payment_hash,
expiry: tlc.lock_time,
hash_algorithm: tlc.hash_algorithm,
}),
};
debug!("Sending AddTlc message: {:?}", &msg);
Expand Down Expand Up @@ -2130,8 +2133,11 @@ impl ChannelActorState {
reason, removed_at, current
);
if let RemoveTlcReason::RemoveTlcFulfill(fulfill) = reason {
let filled_payment_hash: Hash256 =
blake2b_256(fulfill.payment_preimage).into();
let filled_payment_hash: Hash256 = current
.tlc
.hash_algorithm
.hash(fulfill.payment_preimage)
.into();
if current.tlc.payment_hash != filled_payment_hash {
return Err(ProcessingChannelError::InvalidParameter(format!(
"Preimage {:?} is hashed to {}, which does not match payment hash {:?}",
Expand Down Expand Up @@ -2436,7 +2442,7 @@ impl ChannelActorState {
tlcs.iter()
.map(|(tlc, local, remote)| {
[
(if tlc.tlc.is_offered() { [0] } else { [1] }).to_vec(),
vec![tlc.tlc.get_htlc_type()],
tlc.tlc.amount.to_le_bytes().to_vec(),
tlc.tlc.get_hash().to_vec(),
local.serialize().to_vec(),
Expand Down Expand Up @@ -2520,14 +2526,15 @@ impl ChannelActorState {
let preimage = command.preimage.unwrap_or(get_random_preimage());
let payment_hash = command
.payment_hash
.unwrap_or(blake2b_256(&preimage).into());
.unwrap_or_else(|| command.hash_algorithm.hash(&preimage).into());

TLC {
id: TLCId::Offered(id),
amount: command.amount,
payment_hash,
lock_time: command.expiry,
payment_preimage: Some(preimage),
hash_algorithm: command.hash_algorithm,
}
}

Expand All @@ -2551,6 +2558,7 @@ impl ChannelActorState {
payment_hash: message.payment_hash,
lock_time: message.expiry,
payment_preimage: None,
hash_algorithm: message.hash_algorithm,
})
}
}
Expand Down Expand Up @@ -3171,6 +3179,7 @@ impl ChannelActorState {
amount: info.tlc.amount,
payment_hash: info.tlc.payment_hash,
expiry: info.tlc.lock_time,
hash_algorithm: info.tlc.hash_algorithm,
}),
}),
))
Expand Down Expand Up @@ -4170,6 +4179,8 @@ pub struct TLC {
pub payment_hash: Hash256,
/// The preimage of the hash to be sent to the counterparty.
pub payment_preimage: Option<Hash256>,
/// Which hash algorithm is applied on the preimage
pub hash_algorithm: HashAlgorithm,
}

impl TLC {
Expand All @@ -4186,6 +4197,16 @@ impl TLC {
self.id.flip_mut()
}

/// Get the value for the field `htlc_type` in commitment lock witness.
/// - Lowest 1 bit: 0 if the tlc is offered by the remote party, 1 otherwise.
/// - High 7 bits:
/// - 0: ckb hash
/// - 1: sha256
pub fn get_htlc_type(&self) -> u8 {
let offered_flag = if self.is_offered() { 0u8 } else { 1u8 };
((self.hash_algorithm as u8) << 1) + offered_flag
}

fn get_hash(&self) -> ShortHash {
self.payment_hash.as_ref()[..20].try_into().unwrap()
}
Expand Down
49 changes: 37 additions & 12 deletions src/ckb/gen/cfn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7042,6 +7042,7 @@ impl ::core::fmt::Display for AddTlc {
write!(f, ", {}: {}", "amount", self.amount())?;
write!(f, ", {}: {}", "payment_hash", self.payment_hash())?;
write!(f, ", {}: {}", "expiry", self.expiry())?;
write!(f, ", {}: {}", "hash_algorithm", self.hash_algorithm())?;
let extra_count = self.count_extra_fields();
if extra_count != 0 {
write!(f, ", .. ({} fields)", extra_count)?;
Expand All @@ -7056,14 +7057,14 @@ impl ::core::default::Default for AddTlc {
}
}
impl AddTlc {
const DEFAULT_VALUE: [u8; 120] = [
120, 0, 0, 0, 24, 0, 0, 0, 56, 0, 0, 0, 64, 0, 0, 0, 80, 0, 0, 0, 112, 0, 0, 0, 0, 0, 0, 0,
const DEFAULT_VALUE: [u8; 125] = [
125, 0, 0, 0, 28, 0, 0, 0, 60, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 116, 0, 0, 0, 124, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
];
pub const FIELD_COUNT: usize = 5;
pub const FIELD_COUNT: usize = 6;
pub fn total_size(&self) -> usize {
molecule::unpack_number(self.as_slice()) as usize
}
Expand Down Expand Up @@ -7107,11 +7108,17 @@ impl AddTlc {
pub fn expiry(&self) -> Uint64 {
let slice = self.as_slice();
let start = molecule::unpack_number(&slice[20..]) as usize;
let end = molecule::unpack_number(&slice[24..]) as usize;
Uint64::new_unchecked(self.0.slice(start..end))
}
pub fn hash_algorithm(&self) -> Byte {
let slice = self.as_slice();
let start = molecule::unpack_number(&slice[24..]) as usize;
if self.has_extra_fields() {
let end = molecule::unpack_number(&slice[24..]) as usize;
Uint64::new_unchecked(self.0.slice(start..end))
let end = molecule::unpack_number(&slice[28..]) as usize;
Byte::new_unchecked(self.0.slice(start..end))
} else {
Uint64::new_unchecked(self.0.slice(start..))
Byte::new_unchecked(self.0.slice(start..))
}
}
pub fn as_reader<'r>(&'r self) -> AddTlcReader<'r> {
Expand Down Expand Up @@ -7146,6 +7153,7 @@ impl molecule::prelude::Entity for AddTlc {
.amount(self.amount())
.payment_hash(self.payment_hash())
.expiry(self.expiry())
.hash_algorithm(self.hash_algorithm())
}
}
#[derive(Clone, Copy)]
Expand All @@ -7172,6 +7180,7 @@ impl<'r> ::core::fmt::Display for AddTlcReader<'r> {
write!(f, ", {}: {}", "amount", self.amount())?;
write!(f, ", {}: {}", "payment_hash", self.payment_hash())?;
write!(f, ", {}: {}", "expiry", self.expiry())?;
write!(f, ", {}: {}", "hash_algorithm", self.hash_algorithm())?;
let extra_count = self.count_extra_fields();
if extra_count != 0 {
write!(f, ", .. ({} fields)", extra_count)?;
Expand All @@ -7180,7 +7189,7 @@ impl<'r> ::core::fmt::Display for AddTlcReader<'r> {
}
}
impl<'r> AddTlcReader<'r> {
pub const FIELD_COUNT: usize = 5;
pub const FIELD_COUNT: usize = 6;
pub fn total_size(&self) -> usize {
molecule::unpack_number(self.as_slice()) as usize
}
Expand Down Expand Up @@ -7224,11 +7233,17 @@ impl<'r> AddTlcReader<'r> {
pub fn expiry(&self) -> Uint64Reader<'r> {
let slice = self.as_slice();
let start = molecule::unpack_number(&slice[20..]) as usize;
let end = molecule::unpack_number(&slice[24..]) as usize;
Uint64Reader::new_unchecked(&self.as_slice()[start..end])
}
pub fn hash_algorithm(&self) -> ByteReader<'r> {
let slice = self.as_slice();
let start = molecule::unpack_number(&slice[24..]) as usize;
if self.has_extra_fields() {
let end = molecule::unpack_number(&slice[24..]) as usize;
Uint64Reader::new_unchecked(&self.as_slice()[start..end])
let end = molecule::unpack_number(&slice[28..]) as usize;
ByteReader::new_unchecked(&self.as_slice()[start..end])
} else {
Uint64Reader::new_unchecked(&self.as_slice()[start..])
ByteReader::new_unchecked(&self.as_slice()[start..])
}
}
}
Expand Down Expand Up @@ -7283,6 +7298,7 @@ impl<'r> molecule::prelude::Reader<'r> for AddTlcReader<'r> {
Uint128Reader::verify(&slice[offsets[2]..offsets[3]], compatible)?;
Byte32Reader::verify(&slice[offsets[3]..offsets[4]], compatible)?;
Uint64Reader::verify(&slice[offsets[4]..offsets[5]], compatible)?;
ByteReader::verify(&slice[offsets[5]..offsets[6]], compatible)?;
Ok(())
}
}
Expand All @@ -7293,9 +7309,10 @@ pub struct AddTlcBuilder {
pub(crate) amount: Uint128,
pub(crate) payment_hash: Byte32,
pub(crate) expiry: Uint64,
pub(crate) hash_algorithm: Byte,
}
impl AddTlcBuilder {
pub const FIELD_COUNT: usize = 5;
pub const FIELD_COUNT: usize = 6;
pub fn channel_id(mut self, v: Byte32) -> Self {
self.channel_id = v;
self
Expand All @@ -7316,6 +7333,10 @@ impl AddTlcBuilder {
self.expiry = v;
self
}
pub fn hash_algorithm(mut self, v: Byte) -> Self {
self.hash_algorithm = v;
self
}
}
impl molecule::prelude::Builder for AddTlcBuilder {
type Entity = AddTlc;
Expand All @@ -7327,6 +7348,7 @@ impl molecule::prelude::Builder for AddTlcBuilder {
+ self.amount.as_slice().len()
+ self.payment_hash.as_slice().len()
+ self.expiry.as_slice().len()
+ self.hash_algorithm.as_slice().len()
}
fn write<W: molecule::io::Write>(&self, writer: &mut W) -> molecule::io::Result<()> {
let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1);
Expand All @@ -7341,6 +7363,8 @@ impl molecule::prelude::Builder for AddTlcBuilder {
total_size += self.payment_hash.as_slice().len();
offsets.push(total_size);
total_size += self.expiry.as_slice().len();
offsets.push(total_size);
total_size += self.hash_algorithm.as_slice().len();
writer.write_all(&molecule::pack_number(total_size as molecule::Number))?;
for offset in offsets.into_iter() {
writer.write_all(&molecule::pack_number(offset as molecule::Number))?;
Expand All @@ -7350,6 +7374,7 @@ impl molecule::prelude::Builder for AddTlcBuilder {
writer.write_all(self.amount.as_slice())?;
writer.write_all(self.payment_hash.as_slice())?;
writer.write_all(self.expiry.as_slice())?;
writer.write_all(self.hash_algorithm.as_slice())?;
Ok(())
}
fn build(&self) -> Self::Entity {
Expand Down
Loading

0 comments on commit f1970c8

Please sign in to comment.