Skip to main content

lace_rt/
policy.rs

1//! Policy preparation before participant claiming or replacement staging.
2
3use crate::{InterlaceModule, Result};
4pub use lace_sans_io::logic::all_records;
5use lace_sans_io::logic::prepare_facet_constraints;
6
7/// Prepare one exchange operand without performing IO.
8///
9/// Prepared modules work without the `compiler` feature. With that feature,
10/// strings compile one self-contained Lace-120 contribution. Independent
11/// prepared policies combine through `prepare_facet_constraints`.
12pub trait IntoPolicy {
13    fn into_policy(self) -> Result<InterlaceModule>;
14}
15
16impl IntoPolicy for InterlaceModule {
17    fn into_policy(self) -> Result<InterlaceModule> {
18        Ok(prepare_facet_constraints(&[self], &[], &[])?)
19    }
20}
21
22impl IntoPolicy for &InterlaceModule {
23    fn into_policy(self) -> Result<InterlaceModule> {
24        self.clone().into_policy()
25    }
26}
27
28#[cfg(feature = "compiler")]
29impl IntoPolicy for &str {
30    fn into_policy(self) -> Result<InterlaceModule> {
31        Ok(lace_compiler::compile(self)?)
32    }
33}
34
35#[cfg(feature = "compiler")]
36impl IntoPolicy for String {
37    fn into_policy(self) -> Result<InterlaceModule> {
38        self.as_str().into_policy()
39    }
40}
41
42#[cfg(feature = "compiler")]
43impl IntoPolicy for &String {
44    fn into_policy(self) -> Result<InterlaceModule> {
45        self.as_str().into_policy()
46    }
47}
48
49/// Porcelain operands by participant position: the private first participant
50/// adds `veto` to `base`; the target keeps `base`.
51pub(crate) fn private_operands(
52    base: InterlaceModule,
53    veto: &InterlaceModule,
54) -> Result<[InterlaceModule; 2]> {
55    Ok([
56        prepare_facet_constraints(&[base.clone(), veto.clone()], &[], &[])?,
57        base,
58    ])
59}
60
61#[cfg(test)]
62#[test]
63fn porcelain_operands_match_the_cross_runtime_vector() {
64    use lace_sans_io::logic::{rx_disabled, tx_disabled};
65    let vector = include_str!("../../lace-sans-io/tests/vectors/porcelain-operands.txt");
66    let section = |name: &str| {
67        vector
68            .split("== ")
69            .find_map(|part| part.strip_prefix(name)?.strip_prefix('\n'))
70            .expect("vector section")
71            .trim_end_matches('\n')
72    };
73    let texts = |operands: [InterlaceModule; 2]| operands.map(|m| m.canonical_text().to_owned());
74    let policy = InterlaceModule::from_text(section("policy")).unwrap();
75    assert_eq!(
76        texts(private_operands(policy, tx_disabled()).unwrap()),
77        [section("capture-private"), section("capture-target")]
78    );
79    assert_eq!(
80        texts(private_operands(all_records().clone(), rx_disabled()).unwrap()),
81        [section("provider-private"), section("provider-target")]
82    );
83}