diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..485dee6
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+.idea
diff --git a/0000-zmix/README.md b/0000-zmix/README.md
new file mode 100644
index 0000000..464ec42
--- /dev/null
+++ b/0000-zmix/README.md
@@ -0,0 +1,401 @@
+- Feature Name: (mal000002, zmix)
+- Start Date: 05-Feb-2019
+- RFC PR: (leave this empty)
+- Ursa Issue: (leave this empty)
+- Version: 1
+
+# Summary
+[summary]: #summary
+
+Zmix is a library for expressing, constructing, and verifying non-interactive
+zero-knowledge proofs (ZKPs). A broad class of zero-knowledge proofs is
+supported. Schnorr-type proofs are used for many parts and to glue pieces
+together, while individual parts of a proof may use other zero-knowledge
+techniques. There is a PoC [here](https://github.com/lovesh/ursa/blob/zmix/libzmix/src/zkl/sample_proof.rs) but this doc still needs alignment with the PoC.
+
+# Motivation
+[motivation]: #motivation
+
+Zero-knowledge proofs form a cryptographic building block with many
+applications. Within hyperledger, Indy relies heavily on ZKPs to construct
+anonymous credentials. Fabric uses ZKPs to authenticate transactions when
+using the identity mixer membership service provider. Implementing ZKPs
+correctly however is challenging. Zmix aims to offer a secure
+implementation of ZKPs which can be consumed through a simple API, making
+it easier for other projects to use ZKPs.
+
+# Guide-level explanation
+[guide-level-explanation]: #guide-level-explanation
+
+## Introduction
+
+A zero-knowledge proof enables a prover to convince a verifier of the truth
+of some statement about certain values, without revealing those values. For
+example, a prover may know that values `A` and `B` have an equal discrete
+logarithm. That is, for some `x`, `A = g^x` and `B = h^x`. It could
+convince a verifier that this is true by revealing `x`. If the prover would
+rather not disclose `x`, it could instead construct a zero-knowledge proof
+of this statement, and send the resulting proof to the verifier. The
+verifier can now be sure that `log_g(A) = log_h(B)`, without knowing the
+discrete log `x`.
+
+In the example above, there are three components:
+
+- What do we want to prove? That there exists an `x` such that `A = g^x`
+and `B = h^x`.
+
+- How do we know this is true? Because we know `x`.
+
+- How can we prove it? With a zero-knowledge proof that the prover produces
+and the verifier verifies.
+
+In zmix, we have data types corresponding to these three components:
+
+- `ProofSpec`: specifies what we want to prove
+
+- `Witness`: contains the secrets that satisfy the `ProofSpec`.
+
+- `Proof`: the zero-knowledge proof.
+
+The library provides two features: construction and verification of
+zero-knowledge proofs.
+
+To construct a proof, zmix requires a `ProofSpec s` and a `Witness w`
+(which is a valid witness for `p`), and will output a `Proof p`.
+To verify a proof, zmix requires a `ProofSpec s` and a `Proof p`, and will
+output a boolean indicating whether the proof was valid (true) or invalid
+(false).
+Typically a prover will be requested by a verifier to present a proof through
+an artifact (Aries calls such an artifact a proof-request). The prover parses that
+artifact to create a ProofSpec which is then used (with a witness) to
+create a proof. The verifier will use the same process to create a ProofSpec.
+
+
+# Reference-level explanation
+[reference-level-explanation]: #reference-level-explanation
+
+Conceptually, the zmix library will offer the functions:
+
+* `generate_proof(s: ProofSpec, w: Witness) -> Result`
+* `verify_proof(p: Proof, s: ProofSpec) -> Result<(), Error>`
+
+where the
+
+1. proof specification `ProofSpec` contains a list of _statements_ `Statement`, where each statement represents a _part_ of the overall relation being proved
+1. witness `Witness` contains the witnesses for the statements. Each `Statement` can have an associated `StatementWitness`. Witness for some statements might be derived from witnesses of other statements.
+1. proof `Proof` contains the proofs for the statements. Each `Statement` can have an associated `StatementProof` however proofs for statements might be combined in a single `StatementProof`. Bulletproofs is an example where several proofs for statements like range proof, set membership, merkle tree membership etc are combined in a single proof.
+
+```
+pub struct ProofSpec {
+ statements: Vec,
+ ...
+}
+
+pub struct Witness {
+ pub statement_witnesses: HashMap,
+}
+
+pub struct Proof {
+ // Keeping statement_proofs a vector and not a map of statement index -> Proof since several statements can have a single proof, like in case of bulletproofs
+ pub statement_proofs: Vec,
+}
+```
+The library will offer and support various types of statements, such as signatures and commitments.
+To combine and connect all the statements (i.e., the proof's parts) contained in the proof specification, that is, glue all parts together into a single zero-knowledge proof, the library will use _Schnorr proofs_.
+
+For generating a Schnorr proof that encompasses multiple statements, for each statement one requires a _hash contribution_ on the one hand, and a _proof contribution_ based on an aggregation of the hash contributions on the other hand.
+In particular, the library will implement a proof orchestrator that conceptually generates Schnorr proofs as follows:
+
+
+
+For verifying such a Schnorr proof, one again requires (re-computed) hash contributions for each statement.
+In particular, the library's proof orchestrator will conceptually verify a Schnorr proof as follows:
+
+
+
+## Proof Modules
+
+In accordance with the sequence diagrams shown previously, to (re-)generate the hash contributions and the proof contributions, the library will implement the following _proof module_ interface for each supported statement type:
+
+```
+pub trait ProofModule {
+ fn get_hash_contribution(
+ &mut self,
+ witness: StatementWitness
+ ) -> Result, ZkLangError>;
+ fn get_proof_contribution(
+ &mut self,
+ challenge: &FieldElement,
+ ) -> Result;
+ fn verify_proof_contribution(
+ &self,
+ challenge: &FieldElement,
+ proof: StatementProof,
+ ) -> Result;
+}
+```
+
+## Referencing secrets by index
+
+We previously described that the proof specification contains the number of secrets (called messages) involved in the proof as `message_count`, and a list of statements.
+When generating and verifying a proof according to a proof spec, the number of secrets and the various statements are related in the following way:
+assuming an ordered list of size `message_count` where each element represents some particular (unknown) secret involved in the proof, the statements can reference elements (that is, secrets) of that list by index.
+If different statements reference the same index, they effectively reference the same secret.
+
+To illustrate this, consider a statement type for signatures.
+In general, signatures contain at least
+
+1. a public key under which the signature can be verified, and
+1. an *ordered* list of values that are either hidden (that is, secret) or
+revealed (that is, public).
+
+For example, the library will offer a statement type for Boneh Boyen
+Shacham (BBS) signatures as follows:
+
+```
+pub enum Statement {
+ PoKSignatureBBS(PoKSignatureBBS),
+ ...
+}
+
+....
+pub struct PoKSignatureBBS {
+ pk: BBSVerkey,
+ // Messages being revealed.
+ revealed_messages: HashMap,
+}
+```
+
+While each revealed value in the signature statement simply contains
+the actual value, hidden values are qualified with an _index_.
+In accordance with the list metaphor described above, this index must be smaller or equal to the overall number of secrets as specified in the field `message_count` in the proof specification.
+
+### Referencing the same secret from different statements
+
+The index-based approach allows for referring to the *same* secret in the
+overall zero-knowledge proof from *different* statements. For example,
+another important statement type are commitments, such as the following
+Pederson commitment:
+```
+pub enum Statement {
+ ...
+ PedersenCommitment {
+ message_index: usize,
+ commitment: Vec,
+ ...
+ },
+```
+Consider a proof specification with a `message_count` of 2 and the
+following two statements:
+1. a `SignatureBBS` over three values where the first is hidden referring
+to index 0, the second is hidden referring to index 1, and the third is the
+revealed value 42, and
+1. a `PedersenCommitment` referring (via `message_index`) to index 0.
+
+The fact that both the signature and the commitment refer to index 0 means
+that they both refer to the same secret in the overall list of secrets (of
+size `message_count`) involved in the zero-knowledge proof.
+
+### Expressing equality of secrets
+
+The case when *different signature statements* reference the *same* index is special: this means that the underlying secret values in the signatures are *equal*.
+
+## Supported statement types
+
+Zmix plans to offer the following proof modules for the following statement types:
+
+- Signatures
+ - Boneh Boyen Shacham
+ - Pointcheval Sanders
+- Pedersen commitments
+- Bulletproof intervals
+- Bulletproof set membership inclusive and exclusive
+- zk-SNARK set memberships
+- Verifiable encryption
+- Linkable indistinguisable tags (see ia.cr/2011/658) to realize scope pseudonyms
+
+## Structures
+
+### Statements
+
+```rust
+pub enum Statement {
+ /// Boneh Boyen Shacham Signature
+ SignatureBBS {
+ pk: Vec,
+ messages: Vec,
+ },
+ /// Pointcheval Sanders Signature
+ SignaturePS {
+ pk: Vec,
+ messages: Vec,
+ },
+ PedersenCommitment {
+ message_index: usize,
+ commitment: Vec,
+ params: PedersenCommitmentParams,
+ },
+ IntervalBulletproof {
+ message_index: usize,
+ min: Vec,
+ max: Vec,
+ params: Vec,
+ },
+ /// Camenisch Shoup Encryption
+ EncryptionCS {
+ message_index: usize,
+ pk: Vec,
+ ciphertext: Vec,
+ },
+ /// As defined by Bernhard et al., Anonymous attestation with user-controlled linkability (ia.cr/2011/658)
+ LinkableIndistinguishableTagBLS {
+ message_index: usize,
+ tag: Vec,
+ params: Vec,
+ },
+}
+
+pub enum HiddenOrRevealedValue {
+ HiddenValueIndex(usize),
+ RevealedValue(Vec),
+}
+
+pub struct PedersenCommitmentParams(pub Vec);
+```
+
+### Proof Specification
+
+The proof spec follows this data model
+```rust
+#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
+pub struct ProofSpec {
+ #[serde(rename = "messageCount")]
+ pub message_count: usize,
+ pub statements: Vec,
+ pub params: ProofSpecParams,
+}
+
+pub enum ProofSpecParams {
+ BN254,
+ BLS12_381,
+ Ed25519,
+}
+```
+
+For example, a proof spec could be represented in JSON as
+```json
+{
+ "messageCount": 2,
+ "statements": [
+ {
+ "type": "SignatureBBS",
+ "data": {
+ "pk": [
+ 112,
+ 117,
+ 98,
+ 108,
+ 105,
+ 99,
+ 107,
+ 101,
+ 121
+ ],
+ "messages": [
+ {
+ "hiddenValueIndex": 0
+ },
+ {
+ "revealedValue": [
+ 118,
+ 97,
+ 108,
+ 117,
+ 101
+ ]
+ }
+ ]
+ }
+ }
+ ],
+ "params": "BLS12_381"
+}
+
+```
+
+### Witness
+The witness follows this data model
+
+```rust
+/// A witness w is valid w.r.t. a proof specification s if
+/// * w contains one value for each of the (hidden) messages in s, so w.messages.len() == s.message_count
+/// * w contains one statement witness for each statement in s, so w.statement_witnesses.len() == s.statements.len()
+/// * TODO: add further requirements
+pub struct Witness {
+ messages: Vec>,
+ statement_witnesses: Vec,
+}
+
+pub enum StatementWitness {
+ SignatureBBS(SignatureBBSWitness),
+ SignaturePS(SignaturePSWitness),
+ EncryptionCS(EncryptionCSWitness),
+ PedersenCommitment(PedersenCommitmentWitness),
+ IntervalBulletproof, // no witness data needed
+ SetMembershipBulletProofMerkle(MerklePathWitness),
+ SetMembershipEccAccumulator(AccumulatorWitness),
+}
+
+pub struct SignatureBBSWitness {
+ a: PointG1,
+ e: FieldOrderElement,
+ s: FieldOrderElement,
+}
+```
+
+### Proof
+The proof follows this data model
+```rust
+/// A proof p is valid w.r.t. a proof specification s if
+/// * p contains one message s-value for each of the (hidden) messages in s, so p.message_s_values.len() == s.message_count
+/// * p contains one statement proof for each statement in s, so p.statement_proofs.len() == s.statements.len()
+/// * the type of p.statement_proofs[i] corresponds to the type of s.statements[i]
+/// * TODO: add further requirements
+pub struct Proof {
+ // proof contains a single “challenge” value
+ challenge_hash: Vec,
+ message_s_values: Vec>,
+ statement_proofs: Vec,
+}
+
+pub enum StatementProof {
+ SignatureBBS(SignatureBBSProof),
+ SignaturePS(SignaturePSProof),
+ EncryptionCS(EncryptionCSProof),
+ PedersenCommitment(PedersenCommitmentProof),
+ IntervalBulletproof(IntervalBulletproofProof),
+}
+
+pub struct SignatureBBSProof {
+ a_prime: Vec,
+ a_bar: Vec,
+ b_prime: Vec,
+ s_r2: Vec,
+ s_r3: Vec,
+ s_s_prime: Vec,
+ s_e: Vec,
+}
+
+pub struct PedersenCommitmentProof {
+ opening_s_val: Vec,
+}
+```
+
+# Changelog
+[changelog]: #changelog
+
+- [19 Aug 2019] - v1.2 - Update with example data models
+
+- [15 Aug 2019] - v1.1 - Update following recent discussions.
+
+- [5 Feb 2019] - v1 - Initial version.
diff --git a/0000-zmix/proof-spec.json b/0000-zmix/proof-spec.json
new file mode 100644
index 0000000..930c247
--- /dev/null
+++ b/0000-zmix/proof-spec.json
@@ -0,0 +1,272 @@
+{
+ "id": "https://github.com/hyperledger-labs/zmix/docs/zklang_spec.json",
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "ZKLang Proof Specification",
+ "type": "object",
+ "required": ["clauses"],
+ "properties": {
+ "clauses": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "anyOf": [
+ { "$ref": "#/definitions/commitmentClause" },
+ { "$ref": "#/definitions/credentialClause" },
+ { "$ref": "#/definitions/intervalClause" },
+ { "$ref": "#/definitions/setClause" },
+ { "$ref": "#/definitions/verifiableEncryptionClause" },
+ { "$ref": "#/definitions/scopeCommitmentClause" }
+ ]
+ }
+ }
+ },
+ "definitions": {
+ "attrs": {
+ "type": "array",
+ "minItems": 1,
+ "uniqueItems": true,
+ "items": { "type": "integer" }
+ },
+ "pk": {
+ "type": "string"
+ },
+ "commitmentClause": {
+ "type": "object",
+ "required": ["type", "clauseData"],
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": ["commitment"]
+ },
+ "clauseData": {
+ "$ref": "#/definitions/commitment"
+ }
+ }
+ },
+ "credentialClause": {
+ "type": "object",
+ "required": ["type", "clauseData"],
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": ["credential"]
+ },
+ "clauseData": {
+ "$ref": "#/definitions/credential"
+ }
+ }
+ },
+ "intervalClause": {
+ "type": "object",
+ "required": ["type", "clauseData"],
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": ["interval"]
+ },
+ "clauseData": {
+ "$ref": "#/definitions/interval"
+ }
+ }
+ },
+ "setClause": {
+ "type": "object",
+ "required": ["type", "clauseData"],
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": ["set"]
+ },
+ "clauseData": {
+ "$ref": "#/definitions/set"
+ }
+ }
+ },
+ "verifiable_encClause": {
+ "type": "object",
+ "required": ["type", "clauseData"],
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": ["verifiable_enc"]
+ },
+ "clauseData": {
+ "$ref": "#/definitions/verifiable_enc"
+ }
+ }
+ },
+ "scopeCommitmentClause": {
+ "type": "object",
+ "required": ["type", "clauseData"],
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": ["scope_commitment"]
+ },
+ "clauseData": {
+ "$ref": "#/definitions/scope_commitment"
+ }
+ }
+ },
+ "commitment": {
+ "type": "object",
+ "allOf": [
+ {
+ "required": ["attrs"]
+ },
+ {
+ "oneOf": [
+ {
+ "required": ["generators", "modulus"],
+ "not": { "required": ["curve"] }
+ },
+ {
+ "required": ["curve"],
+ "not": { "required": ["generators", "modulus"]}
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "attrs": {
+ "$ref": "#/definitions/attrs"
+ },
+ "generators": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "type": "string"
+ }
+ },
+ "modulus": {
+ "type": "string"
+ },
+ "curve": {
+ "type": "string",
+ "enum": ["x25519", "p256r1", "p384r1", "p512r1", "p256k1", "bls381", "bn254"]
+ }
+ }
+ },
+ "credential": {
+ "type": "object",
+ "required": ["attrs", "pk"],
+ "properties": {
+ "attrs": {
+ "$ref": "#/definitions/attrs"
+ },
+ "pk": {
+ "$ref": "#/definitions/pk"
+ }
+ }
+ },
+ "interval": {
+ "type": "object",
+ "allOf": [
+ {
+ "required": ["attrs"]
+ },
+ {
+ "oneOf": [
+ {
+ "required": ["pk", "min", "max"],
+ "not": { "required": ["sigs"] }
+ },
+ {
+ "required": ["sigs"],
+ "not": { "required": ["pk", "min", "max"] }
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "attrs": {
+ "$ref": "#/definitions/attrs"
+ },
+ "pk": {
+ "$ref": "#/definitions/pk"
+ },
+ "min": {
+ "type": "number"
+ },
+ "max": {
+ "type": "number"
+ },
+ "sigs": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "set": {
+ "type": "object",
+ "allOf": [
+ {
+ "required": ["attrs", "pk", "type"]
+ },
+ {
+ "oneOf": [
+ {
+ "required": ["value"],
+ "not": { "required": ["circuit"] }
+ },
+ {
+ "required": ["circuit"],
+ "not": { "required": ["value"] }
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "attrs": {
+ "$ref": "#/definitions/attrs"
+ },
+ "pk": {
+ "$ref": "#/definitions/pk"
+ },
+ "value": {
+ "type": "integer"
+ },
+ "circuit": {
+ "type": "string"
+ }
+ }
+ },
+ "verifiable_enc": {
+ "type": "object",
+ "required": ["attrs", "pk", "crypto_val", "label"],
+ "properties": {
+ "attrs": {
+ "$ref": "#/definitions/attrs"
+ },
+ "pk": {
+ "$ref": "#/definitions/pk"
+ },
+ "crypto_val": {
+ "type": "string"
+ },
+ "label": {
+ "type": "label",
+ "description": "Decryption policy"
+ }
+ }
+ },
+ "scope_commitment": {
+ "type": "object",
+ "required": ["attrs", "crypto_cal", "scope_label"],
+ "properties": {
+ "attrs": {
+ "$ref": "#/definitions/attrs"
+ },
+ "crypto_val": {
+ "type": "string"
+ },
+ "scope_label": {
+ "type": "string"
+ }
+ }
+ }
+ }
+}
diff --git a/0000-zmix/zmix_flow.png b/0000-zmix/zmix_flow.png
new file mode 100644
index 0000000..6580dfc
Binary files /dev/null and b/0000-zmix/zmix_flow.png differ
diff --git a/0000-zmix/zmix_flow.puml b/0000-zmix/zmix_flow.puml
new file mode 100644
index 0000000..7924a73
--- /dev/null
+++ b/0000-zmix/zmix_flow.puml
@@ -0,0 +1,38 @@
+@startuml
+
+actor Alice as a
+participant "Libzmix" as z
+database "Public\nCrypto\nData" as p
+actor Bob as b
+
+note over a, b
+PR, PO, PF are outside the scope of zmix
+
+end note
+b -> a: PR = proof request
+note right
+Bob can store this somewhere public
+or generate each time
+end note
+opt
+a --> b: PO = proof offer
+end
+a -> a: PF = proof fulfillment
+note right
+Application helps Alice decide
+end note
+a -> p: PD = public data
+a -> a: Proof Spec = PD + PR + PF
+== ZMix ==
+
+a -> z: Proof Spec + Witness
+z -> a: Proof
+
+a -> b: PF, Proof
+b -> p: PD = public data
+b -> b: Proof Spec = PD + PR + PF
+b -> z: PD + Proof
+z -> b: accept or reject
+
+
+@enduml
diff --git a/0000-zmix/zmix_proof_generation.png b/0000-zmix/zmix_proof_generation.png
new file mode 100644
index 0000000..4a000b7
Binary files /dev/null and b/0000-zmix/zmix_proof_generation.png differ
diff --git a/0000-zmix/zmix_proof_generation.puml b/0000-zmix/zmix_proof_generation.puml
new file mode 100644
index 0000000..70fcce4
--- /dev/null
+++ b/0000-zmix/zmix_proof_generation.puml
@@ -0,0 +1,26 @@
+@startuml
+participant "zmix Proof Orchestrator" as po
+participant "Proof Module 1" as pm1
+participant "..." as pm2
+participant "Proof Module N" as pmn
+
+-> po: generate_proof(ProofSpec, Witness)
+
+po -> pm1: get_hash_contribution(...)
+po <- pm1: hc1
+po <-> pm2: ...
+po -> pmn: get_hash_contribution(...)
+po <- pmn: hcN
+
+po -> po: Compute common challenge as\nhash of individual contributions.\nExample: c = hash(hc1 || ... || hcN)
+
+po -> pm1: get_proof_contribution(c, ...)
+po <- pm1: pc1
+po <-> pm2: ...
+po -> pmn: get_proof_contribution(c, ...)
+po <- pmn: pcN
+
+po -> po: Compose proof contributions into a singe proof
+
+<- po: Proof
+@enduml
diff --git a/0000-zmix/zmix_proof_verification.png b/0000-zmix/zmix_proof_verification.png
new file mode 100644
index 0000000..cd93fdb
Binary files /dev/null and b/0000-zmix/zmix_proof_verification.png differ
diff --git a/0000-zmix/zmix_proof_verification.puml b/0000-zmix/zmix_proof_verification.puml
new file mode 100644
index 0000000..ee1c9c0
--- /dev/null
+++ b/0000-zmix/zmix_proof_verification.puml
@@ -0,0 +1,26 @@
+@startuml
+participant "zmix Proof Orchestrator" as po
+participant "Proof Module 1" as pm1
+participant "..." as pm2
+participant "Proof Module N" as pmn
+
+-> po: verify_proof(Proof, ProofSpec)
+
+note over po
+Proof contains a challenge hash c
+end note
+
+po -> pm1: recompute_hash_contribution(c, ...)
+po <- pm1: rhc1
+po <-> pm2: ...
+po -> pmn: recompute_hash_contribution(...)
+po <- pmn: rhcN
+
+po -> po: Recompute common challenge as\nhash of individual contributions.\nExample: c' = hash(rhc1 || ... || rhcN)
+
+note over po
+Proof is valid w.r.t. ProofSpec if c == c'
+end note
+
+<- po: true/false
+@enduml