Browse Source

Add the ability to optionally list parameters for CMZ protocols

You can now write:

CMZProtocol! { proto_name<param1, param2>,
  [the rest is the same as before]
}

to say that param1 and param2 are public constants (Scalars) that will
be specified at runtime.  Then param1 and param2 can appear in the
statements in the statement list in the protocol declaration.

The "<param1, param2>" is optional, and defaults to specifying no
parameters.
Ian Goldberg 6 months ago
parent
commit
cb0e99cd07
1 changed files with 24 additions and 2 deletions
  1. 24 2
      cmzcred_derive/src/lib.rs

+ 24 - 2
cmzcred_derive/src/lib.rs

@@ -159,7 +159,7 @@ pub fn cmzcred_derive(input: TokenStream) -> TokenStream {
 
 
    The format is:
    The format is:
 
 
-   let proto = CMZProtocol! { proto_name,
+   let proto = CMZProtocol! { proto_name<param1,param2>,
      [ A: Cred {
      [ A: Cred {
          attr1: H,
          attr1: H,
          attr2: R,
          attr2: R,
@@ -175,12 +175,13 @@ pub fn cmzcred_derive(input: TokenStream) -> TokenStream {
        attr8: I,
        attr8: I,
        attr9: S,
        attr9: S,
      },
      },
-     A.attr1 == B.attr3,
+     A.attr1 == B.attr3 + param1,
      A.attr1 == C.attr7,
      A.attr1 == C.attr7,
    };
    };
 
 
    The parameters are:
    The parameters are:
    - an identifier for the protocol
    - an identifier for the protocol
+   - an optional angle-bracketed list of parameters (identifiers)
    - a list of zero or more specifications for credentials that will be shown
    - a list of zero or more specifications for credentials that will be shown
    - a list of zero or more specifications for credentials that will be issued
    - a list of zero or more specifications for credentials that will be issued
    - zero or more statements relating the attributes in the credentials
    - zero or more statements relating the attributes in the credentials
@@ -328,6 +329,7 @@ impl<ShowOrIssue: Parse + Copy> Parse for CredSpecVec<ShowOrIssue> {
 #[derive(Debug)]
 #[derive(Debug)]
 struct ProtoSpec {
 struct ProtoSpec {
     proto_name: Ident,
     proto_name: Ident,
+    params: Vec<Ident>,
     show_creds: Vec<CredSpec<ShowSpec>>,
     show_creds: Vec<CredSpec<ShowSpec>>,
     issue_creds: Vec<CredSpec<IssueSpec>>,
     issue_creds: Vec<CredSpec<IssueSpec>>,
     statements: Vec<Expr>,
     statements: Vec<Expr>,
@@ -335,7 +337,26 @@ struct ProtoSpec {
 
 
 impl Parse for ProtoSpec {
 impl Parse for ProtoSpec {
     fn parse(input: ParseStream) -> Result<Self> {
     fn parse(input: ParseStream) -> Result<Self> {
+        let mut params: Vec<Ident> = Vec::new();
         let proto_name: Ident = input.parse()?;
         let proto_name: Ident = input.parse()?;
+        // See if there are optional parameters; Rust does not provide a
+        // convenient angle-bracket parser like it does parens, square
+        // brackets, and braces, so we just roll our own.
+        if input.peek(Token![<]) {
+            input.parse::<Token![<]>()?;
+            loop {
+                if input.peek(Token![>]) {
+                    break;
+                }
+                let param: Ident = input.parse()?;
+                params.push(param);
+                if input.peek(Token![>]) {
+                    break;
+                }
+                input.parse::<Token![,]>()?;
+            }
+            input.parse::<Token![>]>()?;
+        }
         input.parse::<Token![,]>()?;
         input.parse::<Token![,]>()?;
         let showvec: CredSpecVec<ShowSpec> = input.parse()?;
         let showvec: CredSpecVec<ShowSpec> = input.parse()?;
         input.parse::<Token![,]>()?;
         input.parse::<Token![,]>()?;
@@ -347,6 +368,7 @@ impl Parse for ProtoSpec {
 
 
         Ok(ProtoSpec {
         Ok(ProtoSpec {
             proto_name,
             proto_name,
+            params,
             show_creds: showvec.0,
             show_creds: showvec.0,
             issue_creds: issuevec.0,
             issue_creds: issuevec.0,
             statements,
             statements,