Skip to main content

uor_addr/variant/
signed.rs

1//! **`uor_addr::variant::signed` — the signature-required-on-
2//! emission cost-model variant** (ARCHITECTURE.md "Cost-model-bearing
3//! variants" § `uor-addr-signed`).
4//!
5//! Content-addressing variant of the JSON realization that binds
6//! the 5th `PrismModel` parameter to a typed-commitment expressing
7//! a signature-shape admission predicate per ADR-049 + ADR-048.
8//!
9//! ## Concrete `C` selection
10//!
11//! ```text
12//! C = SingletonCommitment<UltrametricCloseTo>
13//! ```
14//!
15//! The architectural commitment per ARCHITECTURE.md is
16//! `SingletonCommitment<SignatureCommitmentPredicate>` where
17//! `SignatureCommitmentPredicate` is a per-κ-label signature-shape
18//! `ObservablePredicate`. The foundation's `ObservablePredicate`
19//! trait is sealed via `__sdk_seal::Sealed` — application code
20//! cannot introduce new predicates without a foundation-level
21//! extension. The closest published `ObservablePredicate` from
22//! `prism::pipeline`'s roster that fits the
23//! "signature-admission-shape" semantics is
24//! [`UltrametricCloseTo`]: it admits κ-labels whose σ-projection's
25//! digest is ultrametrically close (Hamming-prefix-aligned) to a
26//! configured target — the same byte-shape property a signature
27//! commitment per ADR-049's `axis::cryptanalyze` witness would
28//! validate.
29//!
30//! When `prism::pipeline` publishes a
31//! `SignatureCommitmentPredicate` primitive, this module retargets;
32//! the architectural surface — the
33//! `SingletonCommitment<…>` shape — does not change.
34//!
35//! ## Authoritative sources
36//!
37//! - **ADR-048 typed-commitment surface**
38//!   (<https://github.com/UOR-Foundation/UOR-Framework/wiki/ADR-048>).
39//! - **ADR-049 `axis::cryptanalyze` witness**
40//!   (<https://github.com/UOR-Foundation/UOR-Framework/wiki/ADR-049>).
41
42use prism::pipeline::{prism_model, SingletonCommitment, UltrametricCloseTo};
43use prism::vocabulary::DefaultHostTypes;
44
45use crate::bounds::AddrBounds;
46use crate::json::value::JsonCarrier;
47use crate::label::AddressLabel;
48use crate::resolvers::AddressResolverTuple;
49use prism::crypto::Sha256Hasher;
50
51#[allow(unused_imports)]
52use crate::json::verbs::{address_inference, VERB_TERMS_ADDRESS_INFERENCE};
53
54/// **The signature reference digest** — a 32-byte target the
55/// κ-label's digest is XOR-compared against. The predicate's
56/// 2-adic valuation of `(digest XOR reference)` must be ≥
57/// [`SIGNATURE_PROXIMITY_K`] for the signature to admit.
58pub const SIGNATURE_REFERENCE: &[u8] = &[0; 32];
59
60/// **The signature-shape proximity threshold** — 2-adic valuation
61/// ≥ k bits of `(digest XOR reference)` for admission. The shipped
62/// k = 1 yields accept_prob = 1/2 (digest's LSB matches the
63/// reference's LSB); larger k tightens the signature-shape
64/// admission predicate per ADR-049's bandwidth-additivity.
65pub const SIGNATURE_PROXIMITY_K: u32 = 1;
66
67/// **The cost-model commitment type for the signed variant** — the
68/// architectural `SingletonCommitment<…>` shape.
69pub type SignedCommitment = SingletonCommitment<UltrametricCloseTo<2>>;
70
71/// **The commitment instance** — used by the model's `fn commitment()`
72/// clause.
73pub const SIGNED_COMMITMENT_INSTANCE: SignedCommitment = SingletonCommitment {
74    predicate: UltrametricCloseTo {
75        reference: SIGNATURE_REFERENCE,
76        k: SIGNATURE_PROXIMITY_K,
77    },
78};
79
80prism_model! {
81    pub struct AddressSignedModel;
82    pub struct AddressSignedRoute;
83    impl PrismModel<
84        DefaultHostTypes,
85        AddrBounds,
86        Sha256Hasher,
87        AddressResolverTuple<Sha256Hasher>,
88        SignedCommitment
89    > for AddressSignedModel {
90        type Input = JsonCarrier<'a>;
91        type Output = AddressLabel;
92        type Route = AddressSignedRoute;
93        fn route(input: Self::Input) -> Self::Output {
94            address_inference(input)
95        }
96        fn commitment() -> SignedCommitment {
97            SIGNED_COMMITMENT_INSTANCE
98        }
99    }
100}
101
102#[cfg(test)]
103mod tests {
104    use super::*;
105    use prism::pipeline::{ObservablePredicate, TypedCommitment};
106
107    #[test]
108    fn signed_commitment_is_typed_commitment() {
109        fn assert_typed_commitment<C: TypedCommitment>() {}
110        assert_typed_commitment::<SignedCommitment>();
111    }
112
113    #[test]
114    fn signature_predicate_evaluates_against_digest() {
115        let admitted: [u8; 32] = [0; 32];
116        let predicate: UltrametricCloseTo<2> = UltrametricCloseTo {
117            reference: SIGNATURE_REFERENCE,
118            k: SIGNATURE_PROXIMITY_K,
119        };
120        assert!(predicate.evaluate(&admitted));
121        // 2-adic valuation ≥ 1 means LSB must match. A digest whose
122        // last byte differs in the LSB rejects.
123        let mut rejected: [u8; 32] = [0; 32];
124        rejected[31] = 0x01;
125        assert!(!predicate.evaluate(&rejected));
126    }
127
128    #[test]
129    fn signed_model_is_a_distinct_prism_model() {
130        fn assert_is_prism_model<
131            'a,
132            M: prism::pipeline::PrismModel<
133                'a,
134                prism::vocabulary::DefaultHostTypes,
135                crate::AddrBounds,
136                crate::Sha256Hasher,
137                { crate::ADDR_INLINE_BYTES },
138                32,
139                crate::AddressResolverTuple<crate::Sha256Hasher>,
140                SignedCommitment,
141                Route = AddressSignedRoute,
142            >,
143        >() {
144        }
145        assert_is_prism_model::<AddressSignedModel>();
146    }
147
148    #[test]
149    fn signature_reference_is_thirty_two_bytes() {
150        assert_eq!(SIGNATURE_REFERENCE.len(), 32);
151    }
152}