Conversation
Pull Request Test Coverage Report for Build 16945004793Details
💛 - Coveralls |
.cargo/mutants.toml
Outdated
| exclude_re = [ | ||
| "impl Debug", | ||
| "impl fmt::Debug", | ||
| "impl Display", | ||
| "impl fmt::Display", |
There was a problem hiding this comment.
Can regex be used here? something like "impl (fmt::)?(Debug|Display)" ?
There was a problem hiding this comment.
It didn't work initially but I haven't given the cargo mutants a thorough read in this part of the docs
There was a problem hiding this comment.
Ok, nvm that worked, I must have simply formatted my regex wrong when I tried
464fe05 to
e886ef0
Compare
|
There was a mutant reintroduced with the removal of ns1r in #923 however, I realized that the way we tested for it there lacked decent coverage on what was actually mutated. 38da97f covers this mutant in what I believe is a decent way, but it does require quite a lot of testing framework to check it. Just at first glance does anyone else have a better idea on how to test this mutant? rust-payjoin/payjoin/src/core/receive/v2/mod.rs Lines 398 to 422 in 0aa1509 |
spacebear21
left a comment
There was a problem hiding this comment.
Exciting work! I have mostly minor comments, my main concern is regarding the new integration test, see below.
| let txin = &psbt.unsigned_tx.input[0]; | ||
| let mut psbtin = psbt.inputs[0].clone(); | ||
|
|
||
| let transaction: Transaction = bitcoin::consensus::encode::deserialize_hex(raw_tx).unwrap(); | ||
| psbtin.non_witness_utxo = Some(transaction); | ||
|
|
||
| let pair: InternalInputPair = InternalInputPair { txin, psbtin: &psbtin }; | ||
| let validated_utxo = pair.validate_utxo(); | ||
| assert_eq!(validated_utxo.unwrap_err(), InternalPsbtInputError::UnequalTxid); | ||
|
|
||
| let txin = &psbt.unsigned_tx.input[0]; | ||
| let mut psbtin = psbt.inputs[0].clone(); | ||
|
|
||
| let transaction: Transaction = bitcoin::consensus::encode::deserialize_hex(raw_tx).unwrap(); | ||
| psbtin.non_witness_utxo = Some(transaction); | ||
| psbtin.witness_utxo = None; | ||
|
|
||
| let pair: InternalInputPair = InternalInputPair { txin, psbtin: &psbtin }; | ||
| let validated_utxo = pair.validate_utxo(); | ||
| assert_eq!(validated_utxo.unwrap_err(), InternalPsbtInputError::UnequalTxid); |
There was a problem hiding this comment.
I don't see a clear difference between the first and second assert_eq blocks, is it something to do with setting psbtin.witness_utxo = None; explicitly? Explanatory comments might help.
payjoin/src/core/psbt/mod.rs
Outdated
| fn xpub_inputs() { | ||
| let mut psbt: Psbt = PARSED_ORIGINAL_PSBT.clone(); | ||
| let mut map = BTreeMap::new(); | ||
| let secp = Secp256k1::new(); | ||
| let seed = Vec::<u8>::from_hex("BEEFCAFE").unwrap(); | ||
| let xpriv = bip32::Xpriv::new_master(NetworkKind::Main, &seed).unwrap(); | ||
| let xpub: bip32::Xpub = bip32::Xpub::from_priv(&secp, &xpriv); | ||
| let value = (xpriv.fingerprint(&secp), DerivationPath::from_str("42'").unwrap()); | ||
| map.insert(xpub, value); | ||
| psbt.xpub = map; | ||
|
|
||
| let xpub_mutable = psbt.xpub_mut().clone(); | ||
| assert_eq!(xpub_mutable, psbt.xpub); | ||
| } | ||
|
|
||
| #[test] | ||
| fn proprietary_key_inputs() { | ||
| let mut psbt: Psbt = PARSED_ORIGINAL_PSBT.clone(); | ||
| let mut map = BTreeMap::new(); | ||
| let proprietary_key = | ||
| ProprietaryKey { prefix: b"mock_prefix".to_vec(), subtype: 0x00, key: vec![] }; | ||
| let value = FromHex::from_hex("BEEFCAFE").unwrap(); | ||
| map.insert(proprietary_key, value); | ||
| psbt.proprietary = map; | ||
|
|
||
| let proprietary_mutable = psbt.proprietary_mut().clone(); | ||
| assert_eq!(proprietary_mutable, psbt.proprietary); | ||
| } | ||
|
|
||
| #[test] | ||
| fn unknown_inputs() { |
There was a problem hiding this comment.
I don't understand the purpose of these tests.. and also they share a lot of similarities so maybe all belong in one unit?
There was a problem hiding this comment.
These are just coverage checks as these methods aren't really used in any tests/code outside of clearing them out here.
rust-payjoin/payjoin/src/core/send/mod.rs
Line 547 in 0aa1509
There was a problem hiding this comment.
Wouldn't it be preferable to get this coverage by testing clear_unneeded_fields then?
payjoin/tests/integration.rs
Outdated
| let enabled_output_substitution = | ||
| session.pj_uri().to_string().replace("pjos=0", "pjos=1"); |
There was a problem hiding this comment.
Could just remove the pjos parameter:
| let enabled_output_substitution = | |
| session.pj_uri().to_string().replace("pjos=0", "pjos=1"); | |
| let enabled_output_substitution = | |
| session.pj_uri().to_string().replace("&pjos=0", ""); |
payjoin/tests/integration.rs
Outdated
| .assume_checked() | ||
| .check_pj_supported() | ||
| .map_err(|e| e.to_string())?; | ||
| // We need to check that output substitution has been forced anabled |
There was a problem hiding this comment.
typo:
| // We need to check that output substitution has been forced anabled | |
| // We need to check that output substitution is enabled |
(or remove comment)
payjoin/tests/integration.rs
Outdated
| } | ||
|
|
||
| #[tokio::test] | ||
| async fn test_enable_output_substitution_v1_to_v2() -> Result<(), BoxSendSyncError> { |
There was a problem hiding this comment.
This is kind of interesting because under no circumstance should a v2 receiver enable output substitution for v1 sender compatibility. Per BIP 77:
Backwards-compatible receivers MUST disable output substitution by setting pjos=0 to prevent modification by a malicious directory.
This is to avoid a malicious/unsecure directory from modifying the unencrypted PSBT.
I'm not sure how this mutant should be handled, maybe our v1 sender should error if it sees a v2 endpoint with pjos enabled? Paging @DanGould.
There was a problem hiding this comment.
Beyond being a mutant this is also the only coverage we have of that function block for ensuring the output substitution is disabled for a v1 -> v2 sender through the directory. So we would still need a test like this even if we error in this case to ensure that the PSBT hasn't been modified.
...
if params.v == Version::One {
return ReplyableError::Implementation;
}
Though we might want a new error type as a possible malicious modification seems beyond a replyable error IMO.
There was a problem hiding this comment.
I'd be open to merging this PR without this test, perhaps excluding v1 from cargo mutants for the time being until #948 can be resolved.
38da97f to
36f4853
Compare
f3e28ad to
2338e52
Compare
|
Dropping 2338e52 for now as we can address this in a follow-up PR |
This pr adds complete mutation coverage onto the payjoin crate within rust-payjoin. We did discover an outstanding mutant that we still want to explore more as to whether we should modify the source code or keep the behavior as is in payjoin#948.
2338e52 to
583c136
Compare
This PR is to expand our mutant coverage to all files within the
payjoin/src/crate. With the introduction of diff mutations this will allow all files changed within the payjoin crate to be checked for new mutations.