소스 검색

Continue code generation

Ian Goldberg 6 달 전
부모
커밋
93868f628c
2개의 변경된 파일110개의 추가작업 그리고 38개의 파일을 삭제
  1. 104 38
      cmzcred_derive/src/lib.rs
  2. 6 0
      src/lib.rs

+ 104 - 38
cmzcred_derive/src/lib.rs

@@ -16,7 +16,7 @@ the CMZCredential trait for the declared credential.
 
 use darling::FromDeriveInput;
 use proc_macro::{Span, TokenStream};
-use quote::{quote, ToTokens};
+use quote::{format_ident, quote, ToTokens};
 use std::collections::HashMap;
 use syn::parse::{Parse, ParseStream, Result};
 use syn::punctuated::Punctuated;
@@ -278,7 +278,7 @@ impl<ShowOrIssue: Parse> Parse for AttrSpec<ShowOrIssue> {
 struct CredSpec<ShowOrIssue: Parse> {
     id: Ident,
     cred_type: Ident,
-    attrs: HashMap<String, ShowOrIssue>,
+    attrs: HashMap<Ident, ShowOrIssue>,
 }
 
 impl<ShowOrIssue: Parse + Copy> Parse for CredSpec<ShowOrIssue> {
@@ -290,9 +290,9 @@ impl<ShowOrIssue: Parse + Copy> Parse for CredSpec<ShowOrIssue> {
         braced!(content in input);
         let attrspecs: Punctuated<AttrSpec<ShowOrIssue>, Token![,]> =
             content.parse_terminated(AttrSpec::<ShowOrIssue>::parse, Token![,])?;
-        let mut attrs: HashMap<String, ShowOrIssue> = HashMap::new();
+        let mut attrs: HashMap<Ident, ShowOrIssue> = HashMap::new();
         for attrspec in attrspecs.iter() {
-            attrs.insert(attrspec.attr.to_string(), attrspec.spec);
+            attrs.insert(attrspec.attr.clone(), attrspec.spec);
         }
         Ok(Self {
             id,
@@ -481,6 +481,18 @@ fn protocol_macro(
     // The code that will end up in prepare
     let mut prepare_code = quote! {};
 
+    // The code that will end up in handle, before the call to
+    // fill_creds
+    let mut handle_code_pre_fill = quote! {};
+
+    // The code that will end up in handle, after the call to
+    // fill_creds but before the call to authorize
+    let mut handle_code_post_fill = quote! {};
+
+    // The code that will end up in handle, after the call to
+    // authorize
+    let mut handle_code_post_auth = quote! {};
+
     // Are there any Hide or Joint attributes in _any_ credential to be
     // issued?
     let mut any_hide_joint = false;
@@ -488,7 +500,12 @@ fn protocol_macro(
         // Are there any Hide or Joint attributes in this particular
         // credential to be issued?
         let mut cred_hide_joint = false;
+        let iss_cred_id = format_ident!("cred_{}", iss_cred.id);
         for (attr, &spec) in iss_cred.attrs.iter() {
+            // The scoped attribute name, which will be the credential
+            // name, underscore, attribute name.
+            let scoped_attr = format_ident!("attr_{}_{}", iss_cred.id, attr);
+
             if spec == IssueSpec::Hide || spec == IssueSpec::Joint {
                 cred_hide_joint = true;
             }
@@ -532,16 +549,43 @@ fn protocol_macro(
             /* For each Reveal attribute: include attr in Request (client will
                pass the value into prepare)
             */
+            if spec == IssueSpec::Reveal {
+                request_fields.push_scalar(&scoped_attr.to_string());
+                prepare_code = quote! {
+                    #prepare_code
+                    let #scoped_attr = #iss_cred_id.#attr.ok_or(CMZError::RevealAttrMissing)?;
+                };
+            }
 
             /* For each Implicit attribute: does not appear (will be filled in
                by fill_creds on the issuer side and passed into prepare on the
                client side)
             */
+            if spec == IssueSpec::Implicit {
+                prepare_code = quote! {
+                    #prepare_code
+                    let #scoped_attr = #iss_cred_id.#attr.ok_or(CMZError::ImplicitAttrMissing)?;
+                };
+            }
 
             /* For each Set and Joint attribute: the issuer's value will be set
               by fill_creds (for Set) or by handle (for Joint).  Include the
               value in Reply.
             */
+            if spec == IssueSpec::Set {
+                reply_fields.push_scalar(&scoped_attr.to_string());
+                handle_code_post_auth = quote! {
+                    #handle_code_post_auth
+                    let #scoped_attr = #iss_cred_id.#attr.ok_or(CMZError::SetAttrMissing)?;
+                };
+            }
+            if spec == IssueSpec::Joint {
+                reply_fields.push_scalar(&scoped_attr.to_string());
+                handle_code_post_auth = quote! {
+                    #handle_code_post_auth
+                    let #scoped_attr = <Scalar as ff::Field>::random(&mut *rng);
+                };
+            }
         }
         any_hide_joint |= cred_hide_joint;
     }
@@ -666,13 +710,13 @@ fn protocol_macro(
     // immutable reference for each credential to be shown, and an owned
     // value for each credential to be issued.
     let client_show_args = proto_spec.show_creds.iter().map(|c| {
-        let id = &c.id;
+        let id = format_ident!("cred_{}", c.id);
         let cred_type = &c.cred_type;
         quote! { #id: &#cred_type, }
     });
 
     let client_issue_args = proto_spec.issue_creds.iter().map(|c| {
-        let id = &c.id;
+        let id = format_ident!("cred_{}", c.id);
         let cred_type = &c.cred_type;
         quote! { #id: #cred_type, }
     });
@@ -752,39 +796,61 @@ fn protocol_macro(
         quote! { Result<Reply,CMZError> }
     };
 
-    // Temporary: null return value for issuer's handle function
-    let issuer_handle_cred_retvals = proto_spec
-        .show_creds
-        .iter()
-        .map(|c| {
-            let cred_type = &c.cred_type;
-            quote! { #cred_type::default() }
-        })
-        .chain(proto_spec.issue_creds.iter().map(|c| {
-            let cred_type = &c.cred_type;
-            quote! { #cred_type::default() }
-        }));
-
-    let issuer_handle_retval = if tot_num_creds > 1 {
-        quote! { Ok((Reply{}, (#(#issuer_handle_cred_retvals),*))) }
-    } else if tot_num_creds == 1 {
-        quote! { Ok((Reply{}, #(#issuer_handle_cred_retvals)*)) }
-    } else {
-        quote! { Ok(Reply{}) }
-    };
-
     // Build the issuer's handle function
-    let issuer_func = quote! {
-        pub fn handle<F,A>(rng: &mut impl RngCore,
-            request: Request, fill_creds: F, authorize: A)
-            -> #issuer_handle_ret
-        where
-            F: FnOnce(#(#issuer_fill_creds_args)*) ->
-                Result<#issuer_fill_creds_params_ret, CMZError>,
-            A: FnOnce(#(#issuer_authorize_args)*) ->
-                Result<(),CMZError>
-        {
-            #issuer_handle_retval
+    let issuer_func = {
+        // The credential declarations for the issuer's handle function
+        let issuer_handle_cred_decls = proto_spec
+            .show_creds
+            .iter()
+            .map(|c| {
+                let id = format_ident!("cred_{}", c.id);
+                let cred_type = &c.cred_type;
+                quote! { let mut #id = #cred_type::default(); }
+            })
+            .chain(proto_spec.issue_creds.iter().map(|c| {
+                let id = format_ident!("cred_{}", c.id);
+                let cred_type = &c.cred_type;
+                quote! { let mut #id = #cred_type::default(); }
+            }));
+
+        // The return value
+        let issuer_handle_cred_retvals = proto_spec
+            .show_creds
+            .iter()
+            .map(|c| {
+                let id = format_ident!("cred_{}", c.id);
+                quote! { #id }
+            })
+            .chain(proto_spec.issue_creds.iter().map(|c| {
+                let id = format_ident!("cred_{}", c.id);
+                quote! { #id }
+            }));
+
+        let repf = reply_fields.field_iter();
+        let issuer_handle_retval = if tot_num_creds > 1 {
+            quote! { Ok((Reply{#(#repf,)*}, (#(#issuer_handle_cred_retvals),*))) }
+        } else if tot_num_creds == 1 {
+            quote! { Ok((Reply{#(#repf,)*}, #(#issuer_handle_cred_retvals)*)) }
+        } else {
+            quote! { Ok(Reply{#(#repf,)*}) }
+        };
+
+        quote! {
+            pub fn handle<F,A>(rng: &mut impl RngCore,
+                request: Request, fill_creds: F, authorize: A)
+                -> #issuer_handle_ret
+            where
+                F: FnOnce(#(#issuer_fill_creds_args)*) ->
+                    Result<#issuer_fill_creds_params_ret, CMZError>,
+                A: FnOnce(#(#issuer_authorize_args)*) ->
+                    Result<(),CMZError>
+            {
+                #(#issuer_handle_cred_decls)*
+                #handle_code_pre_fill
+                #handle_code_post_fill
+                #handle_code_post_auth
+                #issuer_handle_retval
+            }
         }
     };
 

+ 6 - 0
src/lib.rs

@@ -382,6 +382,12 @@ macro_rules! CMZ {
 /// functions generated by the CMZProtocol family of macros
 #[derive(Error, Debug)]
 pub enum CMZError {
+    #[error("Reveal attribute was not passed to prepare")]
+    RevealAttrMissing,
+    #[error("Implicit attribute was not passed to prepare or handle")]
+    ImplicitAttrMissing,
+    #[error("Set attribute was not passed to handle")]
+    SetAttrMissing,
     #[error("unknown CMZ proof error")]
     Unknown,
 }