mirror of
https://github.com/logos-blockchain/logos-execution-zone.git
synced 2026-03-26 12:13:08 +00:00
add test for empty intersection in circuit
This commit is contained in:
parent
abc30c0ce0
commit
79d70b3a66
Binary file not shown.
Binary file not shown.
BIN
artifacts/program_methods/clock.bin
Normal file
BIN
artifacts/program_methods/clock.bin
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
artifacts/test_program_methods/validity_window_chain_caller.bin
Normal file
BIN
artifacts/test_program_methods/validity_window_chain_caller.bin
Normal file
Binary file not shown.
@ -205,14 +205,16 @@ impl ValidityWindow {
|
||||
self.to
|
||||
}
|
||||
|
||||
/// Sets the inclusive lower bound. Returns `Err` if the updated window would be empty or inverted.
|
||||
/// Sets the inclusive lower bound. Returns `Err` if the updated window would be empty or
|
||||
/// inverted.
|
||||
pub fn set_from(&mut self, id: Option<BlockId>) -> Result<(), InvalidWindow> {
|
||||
let prev = self.from;
|
||||
self.from = id;
|
||||
self.check_window().inspect_err(|_| self.from = prev)
|
||||
}
|
||||
|
||||
/// Sets the exclusive upper bound. Returns `Err` if the updated window would be empty or inverted.
|
||||
/// Sets the exclusive upper bound. Returns `Err` if the updated window would be empty or
|
||||
/// inverted.
|
||||
pub fn set_to(&mut self, id: Option<BlockId>) -> Result<(), InvalidWindow> {
|
||||
let prev = self.to;
|
||||
self.to = id;
|
||||
|
||||
@ -174,12 +174,13 @@ mod tests {
|
||||
#![expect(clippy::shadow_unrelated, reason = "We don't care about it in tests")]
|
||||
|
||||
use nssa_core::{
|
||||
Commitment, DUMMY_COMMITMENT_HASH, EncryptionScheme, Nullifier,
|
||||
Commitment, DUMMY_COMMITMENT_HASH, EncryptionScheme, Nullifier, SharedSecretKey,
|
||||
account::{Account, AccountId, AccountWithMetadata, Nonce, data::Data},
|
||||
};
|
||||
|
||||
use super::*;
|
||||
use crate::{
|
||||
error::NssaError,
|
||||
privacy_preserving_transaction::circuit::execute_and_prove,
|
||||
program::Program,
|
||||
state::{
|
||||
@ -364,4 +365,46 @@ mod tests {
|
||||
.unwrap();
|
||||
assert_eq!(recipient_post, expected_private_account_2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn circuit_fails_when_chained_validity_windows_have_empty_intersection() {
|
||||
let account_keys = test_private_account_keys_1();
|
||||
let pre = AccountWithMetadata::new(
|
||||
Account::default(),
|
||||
false,
|
||||
AccountId::from(&account_keys.npk()),
|
||||
);
|
||||
|
||||
let validity_window_chain_caller = Program::validity_window_chain_caller();
|
||||
let validity_window = Program::validity_window();
|
||||
|
||||
let instruction = Program::serialize_instruction((
|
||||
Some(1_u64),
|
||||
Some(4_u64),
|
||||
validity_window.id(),
|
||||
Some(4_u64),
|
||||
Some(7_u64),
|
||||
))
|
||||
.unwrap();
|
||||
|
||||
let esk = [3; 32];
|
||||
let shared_secret = SharedSecretKey::new(&esk, &account_keys.vpk());
|
||||
|
||||
let program_with_deps = ProgramWithDependencies::new(
|
||||
validity_window_chain_caller,
|
||||
[(validity_window.id(), validity_window)].into(),
|
||||
);
|
||||
|
||||
let result = execute_and_prove(
|
||||
vec![pre],
|
||||
instruction,
|
||||
vec![2],
|
||||
vec![(account_keys.npk(), shared_secret)],
|
||||
vec![],
|
||||
vec![None],
|
||||
&program_with_deps,
|
||||
);
|
||||
|
||||
assert!(matches!(result, Err(NssaError::CircuitProvingError(_))));
|
||||
}
|
||||
}
|
||||
|
||||
@ -292,6 +292,12 @@ mod tests {
|
||||
// `program_methods`
|
||||
Self::new(VALIDITY_WINDOW_ELF.to_vec()).unwrap()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn validity_window_chain_caller() -> Self {
|
||||
use test_program_methods::VALIDITY_WINDOW_CHAIN_CALLER_ELF;
|
||||
Self::new(VALIDITY_WINDOW_CHAIN_CALLER_ELF.to_vec()).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@ -19,6 +19,10 @@ fn main() {
|
||||
let mut account_post = account_pre.clone();
|
||||
account_post.balance = account_post.balance.saturating_sub(balance_to_burn);
|
||||
|
||||
ProgramOutput::new(instruction_words, vec![pre], vec![AccountPostState::new(account_post)])
|
||||
.write();
|
||||
ProgramOutput::new(
|
||||
instruction_words,
|
||||
vec![pre],
|
||||
vec![AccountPostState::new(account_post)],
|
||||
)
|
||||
.write();
|
||||
}
|
||||
|
||||
@ -16,6 +16,10 @@ fn main() {
|
||||
.checked_add(1)
|
||||
.expect("Balance overflow");
|
||||
|
||||
ProgramOutput::new(instruction_words, vec![pre], vec![AccountPostState::new(account_post)])
|
||||
.write();
|
||||
ProgramOutput::new(
|
||||
instruction_words,
|
||||
vec![pre],
|
||||
vec![AccountPostState::new(account_post)],
|
||||
)
|
||||
.write();
|
||||
}
|
||||
|
||||
@ -13,6 +13,10 @@ fn main() {
|
||||
let mut account_post = account_pre.clone();
|
||||
account_post.nonce.public_account_nonce_increment();
|
||||
|
||||
ProgramOutput::new(instruction_words, vec![pre], vec![AccountPostState::new(account_post)])
|
||||
.write();
|
||||
ProgramOutput::new(
|
||||
instruction_words,
|
||||
vec![pre],
|
||||
vec![AccountPostState::new(account_post)],
|
||||
)
|
||||
.write();
|
||||
}
|
||||
|
||||
@ -13,6 +13,10 @@ fn main() {
|
||||
let mut account_post = account_pre.clone();
|
||||
account_post.program_owner = [0, 1, 2, 3, 4, 5, 6, 7];
|
||||
|
||||
ProgramOutput::new(instruction_words, vec![pre], vec![AccountPostState::new(account_post)])
|
||||
.write();
|
||||
ProgramOutput::new(
|
||||
instruction_words,
|
||||
vec![pre],
|
||||
vec![AccountPostState::new(account_post)],
|
||||
)
|
||||
.write();
|
||||
}
|
||||
|
||||
@ -0,0 +1,53 @@
|
||||
use nssa_core::program::{
|
||||
AccountPostState, BlockId, ChainedCall, ProgramId, ProgramInput, ProgramOutput,
|
||||
read_nssa_inputs,
|
||||
};
|
||||
use risc0_zkvm::serde::to_vec;
|
||||
|
||||
/// A program that sets a validity window on its output and chains to another program with a
|
||||
/// potentially different validity window.
|
||||
///
|
||||
/// Instruction: (from_id, until_id, chained_program_id, chained_from, chained_until)
|
||||
/// The initial output uses [from_id, until_id) and chains to `chained_program_id` with
|
||||
/// [chained_from, chained_until).
|
||||
type Instruction = (
|
||||
Option<BlockId>,
|
||||
Option<BlockId>,
|
||||
ProgramId,
|
||||
Option<BlockId>,
|
||||
Option<BlockId>,
|
||||
);
|
||||
|
||||
fn main() {
|
||||
let (
|
||||
ProgramInput {
|
||||
pre_states,
|
||||
instruction: (from_id, until_id, chained_program_id, chained_from, chained_until),
|
||||
},
|
||||
instruction_words,
|
||||
) = read_nssa_inputs::<Instruction>();
|
||||
|
||||
let [pre] = <[_; 1]>::try_from(pre_states.clone())
|
||||
.unwrap_or_else(|_| panic!("Expected exactly one pre state"));
|
||||
let post = pre.account.clone();
|
||||
|
||||
let chained_instruction = to_vec(&(chained_from, chained_until)).unwrap();
|
||||
let chained_call = ChainedCall {
|
||||
program_id: chained_program_id,
|
||||
instruction_data: chained_instruction,
|
||||
pre_states,
|
||||
pda_seeds: vec![],
|
||||
};
|
||||
|
||||
ProgramOutput::new(
|
||||
instruction_words,
|
||||
vec![pre],
|
||||
vec![AccountPostState::new(post)],
|
||||
)
|
||||
.valid_from_id(from_id)
|
||||
.unwrap()
|
||||
.valid_until_id(until_id)
|
||||
.unwrap()
|
||||
.with_chained_calls(vec![chained_call])
|
||||
.write();
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user