Skip to content

Commit 7f43d35

Browse files
authored
Merge branch 'main' into remove-auth-entry-source-signer
2 parents 3d4ffc7 + cadec3f commit 7f43d35

File tree

1 file changed

+56
-4
lines changed

1 file changed

+56
-4
lines changed

cmd/soroban-cli/src/utils.rs

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -298,11 +298,31 @@ pub mod rpc {
298298
));
299299
}
300300
let contract_data_entry = &entries[0];
301-
match LedgerEntryData::from_xdr_base64(&contract_data_entry.xdr, Limits::none())? {
302-
LedgerEntryData::ContractCode(xdr::ContractCodeEntry { code, .. }) => Ok(code.into()),
303-
scval => Err(Error::UnexpectedContractCodeDataType(scval)),
304-
}
301+
let code = match LedgerEntryData::from_xdr_base64(&contract_data_entry.xdr, Limits::none())?
302+
{
303+
LedgerEntryData::ContractCode(xdr::ContractCodeEntry { code, .. }) => Vec::from(code),
304+
scval => return Err(Error::UnexpectedContractCodeDataType(scval)),
305+
};
306+
super::verify_wasm_hash(&code, hash)?;
307+
Ok(code)
308+
}
309+
}
310+
311+
// Uses `Error::NotFound` because `soroban_rpc::Error` has no integrity/mismatch
312+
// variant. The message makes the actual failure reason clear.
313+
fn verify_wasm_hash(code: &[u8], expected_hash: &Hash) -> Result<(), soroban_rpc::Error> {
314+
let computed_hash = Hash(Sha256::digest(code).into());
315+
if computed_hash != *expected_hash {
316+
return Err(soroban_rpc::Error::NotFound(
317+
"WASM hash mismatch".to_string(),
318+
format!(
319+
"expected {}, got {}",
320+
hex::encode(expected_hash.0),
321+
hex::encode(computed_hash.0),
322+
),
323+
));
305324
}
325+
Ok(())
306326
}
307327

308328
#[cfg(test)]
@@ -324,4 +344,36 @@ mod tests {
324344
Err(err) => panic!("Failed to parse contract id: {err}"),
325345
}
326346
}
347+
348+
#[test]
349+
fn test_verify_wasm_hash_matching() {
350+
use sha2::{Digest, Sha256};
351+
use stellar_xdr::curr::Hash;
352+
353+
let wasm_bytes = b"\0asm fake wasm content";
354+
let correct_hash = Hash(Sha256::digest(wasm_bytes).into());
355+
assert!(verify_wasm_hash(wasm_bytes, &correct_hash).is_ok());
356+
}
357+
358+
#[test]
359+
fn test_verify_wasm_hash_mismatch() {
360+
use stellar_xdr::curr::Hash;
361+
362+
let wasm_bytes = b"\0asm fake wasm content";
363+
let wrong_hash = Hash([0xAB; 32]);
364+
let err = verify_wasm_hash(wasm_bytes, &wrong_hash).unwrap_err();
365+
let err_msg = err.to_string();
366+
assert!(
367+
err_msg.contains("WASM hash mismatch"),
368+
"expected 'WASM hash mismatch' in error: {err_msg}"
369+
);
370+
assert!(
371+
err_msg.contains("abababababababababababababababababababababababababababababababab"),
372+
"expected expected-hash in error: {err_msg}"
373+
);
374+
assert!(
375+
err_msg.contains("501dc4e05f47c4713c4a27e89a5b07ed769bb2cc858bcf46de9bed13ae65af29"),
376+
"expected computed-hash in error: {err_msg}"
377+
);
378+
}
327379
}

0 commit comments

Comments
 (0)