Skip to content

Commit 1308ff5

Browse files
committed
sender will set custom records for amp
1 parent 1d5d61f commit 1308ff5

File tree

4 files changed

+121
-7
lines changed

4 files changed

+121
-7
lines changed

crates/fiber-lib/src/fiber/amp.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,58 @@ mod tests {
252252
assert_eq!(children[1], expected_child2);
253253
}
254254

255+
#[test]
256+
fn test_reconstruct_single_child() {
257+
let root = Share::random();
258+
let share = root;
259+
let desc = ChildDesc::new(share, 1);
260+
261+
let children = reconstruct_children(&[desc]);
262+
263+
assert_eq!(children.len(), 1);
264+
assert_eq!(children[0].desc, desc);
265+
266+
// Verify that the child is correctly derived from the reconstructed root
267+
let expected_child = derive_child(root, desc);
268+
assert_eq!(children[0], expected_child);
269+
}
270+
271+
#[test]
272+
fn test_reconstruct_n_children() {
273+
let root = Share::random();
274+
let n = 100;
275+
let mut shares: Vec<Share> = (0..n - 1).map(|_| Share::random()).collect();
276+
let final_share = {
277+
let mut final_share = root;
278+
for share in &shares {
279+
final_share.xor_assign(share);
280+
}
281+
final_share
282+
};
283+
shares.push(final_share);
284+
285+
// onion packet will add ChildDesc
286+
let descs: Vec<ChildDesc> = shares
287+
.iter()
288+
.enumerate()
289+
.map(|(i, &share)| ChildDesc::new(share, i as u32))
290+
.collect();
291+
292+
// last hop will reconstruct children and derive them
293+
let children = reconstruct_children(&descs);
294+
295+
assert_eq!(children.len(), descs.len());
296+
for (i, child) in children.iter().enumerate() {
297+
assert_eq!(child.desc, descs[i]);
298+
}
299+
300+
// Verify that each child is correctly derived from the reconstructed root
301+
for (i, desc) in descs.iter().enumerate() {
302+
let expected_child = derive_child(root, *desc);
303+
assert_eq!(children[i], expected_child);
304+
}
305+
}
306+
255307
#[test]
256308
fn test_reconstruct_empty_children() {
257309
let children = reconstruct_children(&[]);

crates/fiber-lib/src/fiber/network.rs

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ use super::{
7070
use crate::ckb::config::UdtCfgInfos;
7171
use crate::ckb::contracts::{check_udt_script, get_udt_whitelist, is_udt_type_auto_accept};
7272
use crate::ckb::{CkbChainMessage, FundingError, FundingRequest, FundingTx};
73+
use crate::fiber::amp::{reconstruct_children, ChildDesc, Share};
7374
use crate::fiber::channel::{
7475
AddTlcCommand, AddTlcResponse, ChannelEphemeralConfig, ChannelInitializationOperation,
7576
ShutdownCommand, TxCollaborationCommand, TxUpdateCommand, DEFAULT_COMMITMENT_DELAY_EPOCHS,
@@ -88,7 +89,7 @@ use crate::fiber::payment::SessionRoute;
8889
use crate::fiber::payment::{Attempt, AttemptStatus, PaymentSession, PaymentStatus};
8990
use crate::fiber::serde_utils::EntityHex;
9091
use crate::fiber::types::{
91-
FiberChannelMessage, PeeledPaymentOnionPacket, TlcErrPacket, TxSignatures,
92+
AMPPaymentData, FiberChannelMessage, PeeledPaymentOnionPacket, TlcErrPacket, TxSignatures,
9293
};
9394
use crate::fiber::KeyPair;
9495
use crate::invoice::{CkbInvoice, CkbInvoiceStatus, InvoiceStore, PreimageStore};
@@ -659,7 +660,7 @@ impl SendPaymentData {
659660
.is_some_and(|max_parts| max_parts <= 1 || max_parts > PAYMENT_MAX_PARTS_LIMIT)
660661
{
661662
return Err(format!(
662-
"invalid max_parts, value should be in range [1, {}]",
663+
"invalid max_parts, value should be in range [2, {}]",
663664
PAYMENT_MAX_PARTS_LIMIT
664665
));
665666
}
@@ -2384,6 +2385,7 @@ where
23842385
session: &mut PaymentSession,
23852386
) -> Result<Vec<(Attempt, Vec<PaymentHopData>)>, Error> {
23862387
let graph = self.network_graph.read().await;
2388+
let amp_mpp = session.request.allow_atomic_mpp;
23872389
let source = graph.get_source_pubkey();
23882390
let active_parts = session.attempts().filter(|a| a.is_active()).count();
23892391
let mut remain_amount = session.remain_amount();
@@ -2464,13 +2466,61 @@ where
24642466
return Err(Error::SendPaymentError(error));
24652467
}
24662468

2469+
// generate custom records for amp_mpp
2470+
if amp_mpp {
2471+
self.set_custom_records_for_amp_mpp(&mut result, session.payment_hash());
2472+
}
2473+
24672474
for (attempt, _) in &result {
24682475
session.append_attempt(attempt.clone());
24692476
}
24702477

24712478
return Ok(result);
24722479
}
24732480

2481+
fn set_custom_records_for_amp_mpp(
2482+
&self,
2483+
attempts_routers: &mut [(Attempt, Vec<PaymentHopData>)],
2484+
payment_hash: Hash256,
2485+
) {
2486+
let root = Share::random();
2487+
let mut final_secret = root;
2488+
let mut secrets = vec![];
2489+
for _i in 0..(attempts_routers.iter().len() - 1) {
2490+
let secret = Share::random();
2491+
final_secret = final_secret.xor(&secret);
2492+
secrets.push(secret);
2493+
}
2494+
secrets.push(final_secret);
2495+
2496+
let descs: Vec<ChildDesc> = secrets
2497+
.iter()
2498+
.enumerate()
2499+
.map(|(i, &share)| ChildDesc::new(share, i as u32))
2500+
.collect();
2501+
2502+
let children = reconstruct_children(&descs);
2503+
2504+
for (i, desc) in descs.iter().enumerate() {
2505+
let (mut attempt, mut route) = attempts_routers[i].clone();
2506+
2507+
let route_len = route.len();
2508+
let mpp_payment_data =
2509+
AMPPaymentData::new(payment_hash, i as u16, children.len() as u16, desc.share);
2510+
let mut custom_records = route
2511+
.last()
2512+
.expect("expect last hop data")
2513+
.custom_records
2514+
.clone()
2515+
.unwrap_or_default();
2516+
2517+
mpp_payment_data.write(&mut custom_records);
2518+
route[route_len - 1].custom_records = Some(custom_records);
2519+
attempt.hash = children[i].hash;
2520+
attempts_routers[i] = (attempt, route);
2521+
}
2522+
}
2523+
24742524
async fn send_payment_onion_packet(
24752525
&self,
24762526
state: &mut NetworkActorState<S>,

crates/fiber-lib/src/fiber/tests/types.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::{
22
ckb::config::{UdtArgInfo, UdtCellDep, UdtCfgInfos, UdtDep, UdtScript},
33
fiber::{
4+
amp::Share,
45
config::AnnouncedNodeName,
56
features::FeatureVector,
67
gen::{fiber as molecule_fiber, gossip},
@@ -734,7 +735,7 @@ fn test_basic_mpp_custom_records() {
734735
fn test_amp_custom_records() {
735736
let mut payment_custom_records = PaymentCustomRecords::default();
736737
let parent_payment_hash = gen_rand_sha256_hash();
737-
let amp_record = AMPPaymentData::new(parent_payment_hash, 0, 3);
738+
let amp_record = AMPPaymentData::new(parent_payment_hash, 0, 3, Share::random());
738739
amp_record.write(&mut payment_custom_records);
739740

740741
let new_amp_record = AMPPaymentData::read(&payment_custom_records).unwrap();

crates/fiber-lib/src/fiber/types.rs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use super::r#gen::fiber::PubNonceOpt;
1212
use super::serde_utils::{EntityHex, PubNonceAsBytes, SliceBase58, SliceHex};
1313
use crate::ckb::config::{UdtArgInfo, UdtCellDep, UdtCfgInfos, UdtDep, UdtScript};
1414
use crate::ckb::contracts::get_udt_whitelist;
15+
use crate::fiber::amp::Share;
1516
use crate::fiber::network::USER_CUSTOM_RECORDS_MAX_INDEX;
1617
use ckb_jsonrpc_types::CellOutput;
1718
use ckb_types::H256;
@@ -3784,21 +3785,28 @@ impl BasicMppPaymentData {
37843785
}
37853786
}
37863787

3787-
#[derive(Hash, Eq, PartialEq, Debug)]
3788+
#[derive(Eq, PartialEq, Debug)]
37883789
pub struct AMPPaymentData {
37893790
pub parent_payment_hash: Hash256,
37903791
pub total_amp_count: u16,
37913792
pub index: u16,
3793+
pub secret: Share,
37923794
}
37933795

37943796
impl AMPPaymentData {
37953797
pub const CUSTOM_RECORD_KEY: u32 = USER_CUSTOM_RECORDS_MAX_INDEX + 2;
37963798

3797-
pub fn new(parent_payment_hash: Hash256, index: u16, total_amp_count: u16) -> Self {
3799+
pub fn new(
3800+
parent_payment_hash: Hash256,
3801+
index: u16,
3802+
total_amp_count: u16,
3803+
secret: Share,
3804+
) -> Self {
37983805
Self {
37993806
parent_payment_hash,
38003807
total_amp_count,
38013808
index,
3809+
secret,
38023810
}
38033811
}
38043812

@@ -3807,6 +3815,7 @@ impl AMPPaymentData {
38073815
vec.extend_from_slice(self.parent_payment_hash.as_ref());
38083816
vec.extend_from_slice(&self.total_amp_count.to_le_bytes());
38093817
vec.extend_from_slice(&self.index.to_le_bytes());
3818+
vec.extend_from_slice(self.secret.as_bytes());
38103819
vec
38113820
}
38123821

@@ -3821,16 +3830,18 @@ impl AMPPaymentData {
38213830
.data
38223831
.get(&Self::CUSTOM_RECORD_KEY)
38233832
.and_then(|data| {
3824-
if data.len() != 32 + 4 {
3833+
if data.len() != 32 + 4 + 32 {
38253834
return None;
38263835
}
38273836
let parent_hash: [u8; 32] = data[..32].try_into().unwrap();
38283837
let total_amp_count = u16::from_le_bytes(data[32..34].try_into().unwrap());
3829-
let index = u16::from_le_bytes(data[34..].try_into().unwrap());
3838+
let index = u16::from_le_bytes(data[34..36].try_into().unwrap());
3839+
let secret = Share::new(data[36..68].try_into().unwrap());
38303840
Some(Self::new(
38313841
Hash256::from(parent_hash),
38323842
index,
38333843
total_amp_count,
3844+
secret,
38343845
))
38353846
})
38363847
}

0 commit comments

Comments
 (0)