mirror of
https://github.com/logos-blockchain/lssa.git
synced 2026-06-10 11:09:58 +00:00
Merge pull request #515 from logos-blockchain/fix/pp-proof-deserialize-panic
This commit is contained in:
commit
4577f2cbcd
@ -17,6 +17,7 @@ ignore = [
|
||||
{ id = "RUSTSEC-2026-0119", reason = "`hickory-proto` v0.25.0-alpha.5 is present transitively from logos crates, modification may break integration" },
|
||||
|
||||
{ id = "RUSTSEC-2024-0370", reason = "transitive dependency of `logos-blockchain-http-api-common`, can't do anything than wait for upstream fix" },
|
||||
{ id = "RUSTSEC-2026-0173", reason = "`proc-macro-error2` is unmaintained; pulled in transitively via `leptos_macro` and `overwatch-derive`, waiting on upstream fix" },
|
||||
]
|
||||
yanked = "deny"
|
||||
unused-ignored-advisory = "deny"
|
||||
|
||||
@ -31,7 +31,9 @@ impl Proof {
|
||||
}
|
||||
|
||||
pub(crate) fn is_valid_for(&self, circuit_output: &PrivacyPreservingCircuitOutput) -> bool {
|
||||
let inner: InnerReceipt = borsh::from_slice(&self.0).unwrap();
|
||||
let Ok(inner) = borsh::from_slice::<InnerReceipt>(&self.0) else {
|
||||
return false;
|
||||
};
|
||||
let receipt = Receipt::new(inner, circuit_output.to_bytes());
|
||||
receipt.verify(PRIVACY_PRESERVING_CIRCUIT_ID).is_ok()
|
||||
}
|
||||
|
||||
@ -930,4 +930,56 @@ mod tests {
|
||||
"recipient should receive nothing"
|
||||
);
|
||||
}
|
||||
|
||||
/// Regression test: a `PrivacyPreservingTransaction` carrying a structurally invalid
|
||||
/// proof must be rejected with a clean `Err`.
|
||||
#[test]
|
||||
fn privacy_garbage_proof_is_rejected() {
|
||||
use lee_core::{
|
||||
Commitment,
|
||||
account::Account,
|
||||
program::{BlockValidityWindow, TimestampValidityWindow},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
PrivacyPreservingTransaction,
|
||||
privacy_preserving_transaction::{
|
||||
circuit::Proof, message::Message, witness_set::WitnessSet,
|
||||
},
|
||||
};
|
||||
|
||||
let state = V03State::new_with_genesis_accounts(&[], vec![], 0);
|
||||
|
||||
// Minimal message that passes every check up to proof verification: a single
|
||||
// commitment satisfies the non-empty requirement, no signers makes the
|
||||
// nonce/signature checks vacuously true, and unbounded validity windows are valid
|
||||
// for any block/timestamp.
|
||||
let account_id = AccountId::from(&PublicKey::new_from_private_key(
|
||||
&PrivateKey::try_new([1_u8; 32]).unwrap(),
|
||||
));
|
||||
let commitment = Commitment::new(&account_id, &Account::default());
|
||||
let message = Message {
|
||||
public_account_ids: vec![],
|
||||
nonces: vec![],
|
||||
public_post_states: vec![],
|
||||
encrypted_private_post_states: vec![],
|
||||
new_commitments: vec![commitment],
|
||||
new_nullifiers: vec![],
|
||||
block_validity_window: BlockValidityWindow::new_unbounded(),
|
||||
timestamp_validity_window: TimestampValidityWindow::new_unbounded(),
|
||||
};
|
||||
|
||||
// Garbage proof bytes: not a valid borsh-encoded `InnerReceipt`.
|
||||
let garbage_proof = Proof::from_inner(vec![0xff_u8; 64]);
|
||||
let witness_set = WitnessSet::for_message(&message, garbage_proof, &[]);
|
||||
let tx = PrivacyPreservingTransaction::new(message, witness_set);
|
||||
|
||||
let result = ValidatedStateDiff::from_privacy_preserving_transaction(&tx, &state, 1, 0);
|
||||
|
||||
match result {
|
||||
Err(LeeError::InvalidPrivacyPreservingProof) => {}
|
||||
Err(other) => panic!("expected InvalidPrivacyPreservingProof, got {other:?}"),
|
||||
Ok(_) => panic!("garbage proof was accepted instead of rejected"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user