Skip to content

Commit 66c0613

Browse files
committed
add test for mixed
1 parent c4d5d80 commit 66c0613

File tree

4 files changed

+83
-10
lines changed

4 files changed

+83
-10
lines changed

programs/solana/programs/ics26-router/src/instructions/ack_packet.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,14 +144,15 @@ pub fn ack_packet<'info>(
144144

145145
let payload = packet::get_single_payload(&packet)?;
146146

147-
let total_payload_chunks = total_payload_chunks(&msg.packet.payloads);
147+
let total_payload_chunks = total_payload_chunks(&msg.packet.payloads)?;
148148
let proof_data = chunking::assemble_proof_chunks(chunking::AssembleProofParams {
149149
remaining_accounts: ctx.remaining_accounts,
150150
relayer: &ctx.accounts.relayer,
151151
submitter: ctx.accounts.relayer.key(),
152152
client_id: &msg.packet.source_client,
153153
sequence: msg.packet.sequence,
154154
delivery: &msg.proof.data,
155+
// proof chunks come after payload chunks
155156
start_index: total_payload_chunks,
156157
})?;
157158

programs/solana/programs/ics26-router/src/instructions/recv_packet.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ pub fn recv_packet<'info>(
162162

163163
let payload = packet::get_single_payload(&packet)?;
164164

165-
let total_payload_chunks = total_payload_chunks(&msg.packet.payloads);
165+
let total_payload_chunks = total_payload_chunks(&msg.packet.payloads)?;
166166

167167
let proof_data = chunking::assemble_proof_chunks(chunking::AssembleProofParams {
168168
remaining_accounts: ctx.remaining_accounts,
@@ -171,6 +171,7 @@ pub fn recv_packet<'info>(
171171
client_id: &msg.packet.dest_client,
172172
sequence: msg.packet.sequence,
173173
delivery: &msg.proof.data,
174+
// proof chunks come after payload chunks
174175
start_index: total_payload_chunks,
175176
})?;
176177

programs/solana/programs/ics26-router/src/instructions/timeout_packet.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,14 +143,15 @@ pub fn timeout_packet<'info>(
143143

144144
let payload = packet::get_single_payload(&packet)?;
145145

146-
let total_payload_chunks = total_payload_chunks(&msg.packet.payloads);
146+
let total_payload_chunks = total_payload_chunks(&msg.packet.payloads)?;
147147
let proof_data = chunking::assemble_proof_chunks(chunking::AssembleProofParams {
148148
remaining_accounts: ctx.remaining_accounts,
149149
relayer: &ctx.accounts.relayer,
150150
submitter: ctx.accounts.relayer.key(),
151151
client_id: &msg.packet.source_client,
152152
sequence: msg.packet.sequence,
153153
delivery: &msg.proof.data,
154+
// proof chunks come after payload chunks
154155
start_index: total_payload_chunks,
155156
})?;
156157

programs/solana/programs/ics26-router/src/utils/chunking.rs

Lines changed: 77 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -151,14 +151,22 @@ pub fn assemble_single_payload_chunks(params: AssemblePayloadParams) -> Result<V
151151
Ok(payload_data)
152152
}
153153

154-
pub fn total_payload_chunks(payloads: &[MsgPayload]) -> usize {
155-
payloads
154+
pub fn total_payload_chunks(payloads: &[MsgPayload]) -> Result<usize> {
155+
require!(
156+
payloads.windows(2).all(|w| {
157+
matches!(
158+
(&w[0].data, &w[1].data),
159+
(Delivery::Inline { .. }, Delivery::Inline { .. })
160+
| (Delivery::Chunked { .. }, Delivery::Chunked { .. })
161+
)
162+
}),
163+
RouterError::MixedDeliveryModes
164+
);
165+
166+
Ok(payloads
156167
.iter()
157-
.filter_map(|p| match &p.data {
158-
Delivery::Chunked { total_chunks } => Some(*total_chunks as usize),
159-
Delivery::Inline { .. } => None,
160-
})
161-
.sum()
168+
.map(|p| p.data.total_chunks() as usize)
169+
.sum())
162170
}
163171

164172
/// Filter out chunk accounts from `remaining_accounts` before passing to IBC app CPI
@@ -416,6 +424,68 @@ pub fn validate_and_reconstruct_packet(
416424
mod tests {
417425
use super::*;
418426

427+
#[test]
428+
fn test_total_payload_chunks_rejects_mixed_delivery() {
429+
let payloads = vec![
430+
MsgPayload {
431+
source_port: "port".to_string(),
432+
dest_port: "port".to_string(),
433+
version: "1".to_string(),
434+
encoding: "json".to_string(),
435+
data: Delivery::Inline {
436+
data: b"data".to_vec(),
437+
},
438+
},
439+
MsgPayload {
440+
source_port: "port".to_string(),
441+
dest_port: "port".to_string(),
442+
version: "1".to_string(),
443+
encoding: "json".to_string(),
444+
data: Delivery::Chunked { total_chunks: 2 },
445+
},
446+
];
447+
448+
let result = total_payload_chunks(&payloads);
449+
assert!(result.is_err());
450+
}
451+
452+
#[test]
453+
fn test_total_payload_chunks_all_inline() {
454+
let payloads = vec![MsgPayload {
455+
source_port: "port".to_string(),
456+
dest_port: "port".to_string(),
457+
version: "1".to_string(),
458+
encoding: "json".to_string(),
459+
data: Delivery::Inline {
460+
data: b"data".to_vec(),
461+
},
462+
}];
463+
464+
assert_eq!(total_payload_chunks(&payloads).unwrap(), 0);
465+
}
466+
467+
#[test]
468+
fn test_total_payload_chunks_all_chunked() {
469+
let payloads = vec![
470+
MsgPayload {
471+
source_port: "port".to_string(),
472+
dest_port: "port".to_string(),
473+
version: "1".to_string(),
474+
encoding: "json".to_string(),
475+
data: Delivery::Chunked { total_chunks: 2 },
476+
},
477+
MsgPayload {
478+
source_port: "port".to_string(),
479+
dest_port: "port".to_string(),
480+
version: "1".to_string(),
481+
encoding: "json".to_string(),
482+
data: Delivery::Chunked { total_chunks: 3 },
483+
},
484+
];
485+
486+
assert_eq!(total_payload_chunks(&payloads).unwrap(), 5);
487+
}
488+
419489
#[test]
420490
fn test_validate_and_reconstruct_packet_inline_mode_success() {
421491
let packet = solana_ibc_types::MsgPacket {

0 commit comments

Comments
 (0)