# Block Qualified Grant Conclusion <div style="display:flex; flex-direction:row; justify-content:space-between; padding-bottom:15px"> <a style="display:flex; flex-direction:row; align-items:center; justify-content:center; width:100%;" href="https://github.com/0xdeenz/bq2" target="_blank" aria_label="bq2 monorepo"> <svg xmlns="http://www.w3.org/2000/svg" width="17" viewBox="0 0 448 512"><path d="M400 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zM277.3 415.7c-8.4 1.5-11.5-3.7-11.5-8 0-5.4.2-33 .2-55.3 0-15.6-5.2-25.5-11.3-30.7 37-4.1 76-9.2 76-73.1 0-18.2-6.5-27.3-17.1-39 1.7-4.3 7.4-22-1.7-45-13.9-4.3-45.7 17.9-45.7 17.9-13.2-3.7-27.5-5.6-41.6-5.6-14.1 0-28.4 1.9-41.6 5.6 0 0-31.8-22.2-45.7-17.9-9.1 22.9-3.5 40.6-1.7 45-10.6 11.7-15.6 20.8-15.6 39 0 63.6 37.3 69 74.3 73.1-4.8 4.3-9.1 11.7-10.6 22.3-9.5 4.3-33.8 11.7-48.3-13.9-9.1-15.8-25.5-17.1-25.5-17.1-16.2-.2-1.1 10.2-1.1 10.2 10.8 5 18.4 24.2 18.4 24.2 9.7 29.7 56.1 19.7 56.1 19.7 0 13.9.2 36.5.2 40.6 0 4.3-3 9.5-11.5 8-66-22.1-112.2-84.9-112.2-158.3 0-91.8 70.2-161.5 162-161.5S388 165.6 388 257.4c.1 73.4-44.7 136.3-110.7 158.3zm-98.1-61.1c-1.9.4-3.7-.4-3.9-1.7-.2-1.5 1.1-2.8 3-3.2 1.9-.2 3.7.6 3.9 1.9.3 1.3-1 2.6-3 3zm-9.5-.9c0 1.3-1.5 2.4-3.5 2.4-2.2.2-3.7-.9-3.7-2.4 0-1.3 1.5-2.4 3.5-2.4 1.9-.2 3.7.9 3.7 2.4zm-13.7-1.1c-.4 1.3-2.4 1.9-4.1 1.3-1.9-.4-3.2-1.9-2.8-3.2.4-1.3 2.4-1.9 4.1-1.5 2 .6 3.3 2.1 2.8 3.4zm-12.3-5.4c-.9 1.1-2.8.9-4.3-.6-1.5-1.3-1.9-3.2-.9-4.1.9-1.1 2.8-.9 4.3.6 1.3 1.3 1.8 3.3.9 4.1zm-9.1-9.1c-.9.6-2.6 0-3.7-1.5s-1.1-3.2 0-3.9c1.1-.9 2.8-.2 3.7 1.3 1.1 1.5 1.1 3.3 0 4.1zm-6.5-9.7c-.9.9-2.4.4-3.5-.6-1.1-1.3-1.3-2.8-.4-3.5.9-.9 2.4-.4 3.5.6 1.1 1.3 1.3 2.8.4 3.5zm-6.7-7.4c-.4.9-1.7 1.1-2.8.4-1.3-.6-1.9-1.7-1.5-2.6.4-.6 1.5-.9 2.8-.4 1.3.7 1.9 1.8 1.5 2.6z"/></svg> &nbsp;bq2 monorepo </a> <a style="display:flex; flex-direction:row; align-items:center; justify-content:center; width:100%" href="https://github.com/0xdeenz/bq2-subgraph" target="_blank" aria_label="bq2 subgraph"> <svg xmlns="http://www.w3.org/2000/svg" width="17" viewBox="0 0 448 512"><path d="M400 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zM277.3 415.7c-8.4 1.5-11.5-3.7-11.5-8 0-5.4.2-33 .2-55.3 0-15.6-5.2-25.5-11.3-30.7 37-4.1 76-9.2 76-73.1 0-18.2-6.5-27.3-17.1-39 1.7-4.3 7.4-22-1.7-45-13.9-4.3-45.7 17.9-45.7 17.9-13.2-3.7-27.5-5.6-41.6-5.6-14.1 0-28.4 1.9-41.6 5.6 0 0-31.8-22.2-45.7-17.9-9.1 22.9-3.5 40.6-1.7 45-10.6 11.7-15.6 20.8-15.6 39 0 63.6 37.3 69 74.3 73.1-4.8 4.3-9.1 11.7-10.6 22.3-9.5 4.3-33.8 11.7-48.3-13.9-9.1-15.8-25.5-17.1-25.5-17.1-16.2-.2-1.1 10.2-1.1 10.2 10.8 5 18.4 24.2 18.4 24.2 9.7 29.7 56.1 19.7 56.1 19.7 0 13.9.2 36.5.2 40.6 0 4.3-3 9.5-11.5 8-66-22.1-112.2-84.9-112.2-158.3 0-91.8 70.2-161.5 162-161.5S388 165.6 388 257.4c.1 73.4-44.7 136.3-110.7 158.3zm-98.1-61.1c-1.9.4-3.7-.4-3.9-1.7-.2-1.5 1.1-2.8 3-3.2 1.9-.2 3.7.6 3.9 1.9.3 1.3-1 2.6-3 3zm-9.5-.9c0 1.3-1.5 2.4-3.5 2.4-2.2.2-3.7-.9-3.7-2.4 0-1.3 1.5-2.4 3.5-2.4 1.9-.2 3.7.9 3.7 2.4zm-13.7-1.1c-.4 1.3-2.4 1.9-4.1 1.3-1.9-.4-3.2-1.9-2.8-3.2.4-1.3 2.4-1.9 4.1-1.5 2 .6 3.3 2.1 2.8 3.4zm-12.3-5.4c-.9 1.1-2.8.9-4.3-.6-1.5-1.3-1.9-3.2-.9-4.1.9-1.1 2.8-.9 4.3.6 1.3 1.3 1.8 3.3.9 4.1zm-9.1-9.1c-.9.6-2.6 0-3.7-1.5s-1.1-3.2 0-3.9c1.1-.9 2.8-.2 3.7 1.3 1.1 1.5 1.1 3.3 0 4.1zm-6.5-9.7c-.9.9-2.4.4-3.5-.6-1.1-1.3-1.3-2.8-.4-3.5.9-.9 2.4-.4 3.5.6 1.1 1.3 1.3 2.8.4 3.5zm-6.7-7.4c-.4.9-1.7 1.1-2.8.4-1.3-.6-1.9-1.7-1.5-2.6.4-.6 1.5-.9 2.8-.4 1.3.7 1.9 1.8 1.5 2.6z"/></svg> &nbsp;bq2 subgraph </a> <a style="display:flex; flex-direction:row; align-items:center; justify-content:center; width:100%" href="https://github.com/0xdeenz/bq2-site" target="_blank" aria_label="bq2 site"> <svg xmlns="http://www.w3.org/2000/svg" width="17" viewBox="0 0 448 512"><path d="M400 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zM277.3 415.7c-8.4 1.5-11.5-3.7-11.5-8 0-5.4.2-33 .2-55.3 0-15.6-5.2-25.5-11.3-30.7 37-4.1 76-9.2 76-73.1 0-18.2-6.5-27.3-17.1-39 1.7-4.3 7.4-22-1.7-45-13.9-4.3-45.7 17.9-45.7 17.9-13.2-3.7-27.5-5.6-41.6-5.6-14.1 0-28.4 1.9-41.6 5.6 0 0-31.8-22.2-45.7-17.9-9.1 22.9-3.5 40.6-1.7 45-10.6 11.7-15.6 20.8-15.6 39 0 63.6 37.3 69 74.3 73.1-4.8 4.3-9.1 11.7-10.6 22.3-9.5 4.3-33.8 11.7-48.3-13.9-9.1-15.8-25.5-17.1-25.5-17.1-16.2-.2-1.1 10.2-1.1 10.2 10.8 5 18.4 24.2 18.4 24.2 9.7 29.7 56.1 19.7 56.1 19.7 0 13.9.2 36.5.2 40.6 0 4.3-3 9.5-11.5 8-66-22.1-112.2-84.9-112.2-158.3 0-91.8 70.2-161.5 162-161.5S388 165.6 388 257.4c.1 73.4-44.7 136.3-110.7 158.3zm-98.1-61.1c-1.9.4-3.7-.4-3.9-1.7-.2-1.5 1.1-2.8 3-3.2 1.9-.2 3.7.6 3.9 1.9.3 1.3-1 2.6-3 3zm-9.5-.9c0 1.3-1.5 2.4-3.5 2.4-2.2.2-3.7-.9-3.7-2.4 0-1.3 1.5-2.4 3.5-2.4 1.9-.2 3.7.9 3.7 2.4zm-13.7-1.1c-.4 1.3-2.4 1.9-4.1 1.3-1.9-.4-3.2-1.9-2.8-3.2.4-1.3 2.4-1.9 4.1-1.5 2 .6 3.3 2.1 2.8 3.4zm-12.3-5.4c-.9 1.1-2.8.9-4.3-.6-1.5-1.3-1.9-3.2-.9-4.1.9-1.1 2.8-.9 4.3.6 1.3 1.3 1.8 3.3.9 4.1zm-9.1-9.1c-.9.6-2.6 0-3.7-1.5s-1.1-3.2 0-3.9c1.1-.9 2.8-.2 3.7 1.3 1.1 1.5 1.1 3.3 0 4.1zm-6.5-9.7c-.9.9-2.4.4-3.5-.6-1.1-1.3-1.3-2.8-.4-3.5.9-.9 2.4-.4 3.5.6 1.1 1.3 1.3 2.8.4 3.5zm-6.7-7.4c-.4.9-1.7 1.1-2.8.4-1.3-.6-1.9-1.7-1.5-2.6.4-.6 1.5-.9 2.8-.4 1.3.7 1.9 1.8 1.5 2.6z"/></svg> &nbsp;bq2 site </a> </div> <div style="display:flex; flex-direction:row; justify-content:space-between"> <a style="display:flex; flex-direction:row; align-items:center; justify-content:center; width:100%" href="https://deenz.gitbook.io/bq2/getting-started/readme" target="_blank" aria_label="twitter"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" width="17px"><path d="M448 360V24c0-13.3-10.7-24-24-24H96C43 0 0 43 0 96v320c0 53 43 96 96 96h328c13.3 0 24-10.7 24-24v-16c0-7.5-3.5-14.3-8.9-18.7-4.2-15.4-4.2-59.3 0-74.7 5.4-4.3 8.9-11.1 8.9-18.6zM128 134c0-3.3 2.7-6 6-6h212c3.3 0 6 2.7 6 6v20c0 3.3-2.7 6-6 6H134c-3.3 0-6-2.7-6-6v-20zm0 64c0-3.3 2.7-6 6-6h212c3.3 0 6 2.7 6 6v20c0 3.3-2.7 6-6 6H134c-3.3 0-6-2.7-6-6v-20zm253.4 250H96c-17.7 0-32-14.3-32-32 0-17.6 14.4-32 32-32h285.4c-1.9 17.1-1.9 46.9 0 64z"/></svg> &nbsp;Read the docs </a> <a style="display:flex; flex-direction:row; align-items:center; justify-content:center; width:100%" href="https://twitter.com/0xdeenz" target="_blank" aria_label="twitter"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" width="17px"><path d="M400 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zm-48.9 158.8c.2 2.8.2 5.7.2 8.5 0 86.7-66 186.6-186.6 186.6-37.2 0-71.7-10.8-100.7-29.4 5.3.6 10.4.8 15.8.8 30.7 0 58.9-10.4 81.4-28-28.8-.6-53-19.5-61.3-45.5 10.1 1.5 19.2 1.5 29.6-1.2-30-6.1-52.5-32.5-52.5-64.4v-.8c8.7 4.9 18.9 7.9 29.6 8.3a65.447 65.447 0 0 1-29.2-54.6c0-12.2 3.2-23.4 8.9-33.1 32.3 39.8 80.8 65.8 135.2 68.6-9.3-44.5 24-80.6 64-80.6 18.9 0 35.9 7.9 47.9 20.7 14.8-2.8 29-8.3 41.6-15.8-4.9 15.2-15.2 28-28.8 36.1 13.2-1.4 26-5.1 37.8-10.2-8.9 13.1-20.1 24.7-32.9 34z"/></svg> &nbsp;Reach out on Twitter </a> </div> ## Introduction Earlier this year I received a [grant](https://mirror.xyz/privacy-scaling-explorations.eth/5w1v6rxpP-E03rWDr3RliPyFJkptQwIPzet3Vb5jdcI) from the Ethereum Foundation's [Privacy and Scaling Explorations](https://appliedzkp.org/) to develop [Block Qualified](https://github.com/0xdeenz/bq2). This protocol allows users to gain credentials by solving tests *directly on-chain*: we use zero-knowledge proofs to ensure these solutions remain a secret, so cheating becomes mathematically unfeasible. Additionally, we integrate with the [Semaphore protocol](http://semaphore.appliedzkp.org/), which allows users to prove their membership of a group and send signals without revealing their original identity. The end result is a protocol that allows users to: - gain credentials by solving tests **without revealing their solutions**, and - make claims that they own these credentials **without revealing their identities**. Block Qualified allows anyone to design their own open education platform, where users can: - Earn credentials attesting to their knowledge. - Anonymously prove ownership of their credentials. - Anonymously prove that they obtained a grade above a certain threshold. - Anonymously rate credential issuers. All of this being done directly on-chain, with verifiable data, and preserving the privacy of users via zk-proofs. Additionally, Block Qualified has native support for two kinds of credentials: - **Test Credentials**: containing both multiple choice and open answer questions, which can also be restricted to owners of other credentials. - **Legacy Credentials:** which can be used to integrate existing credentials into the platform, allowing recipients to generate these anonymous proofs. ## Tech Stack The protocol is built on a comprehensive tech stack: - The [circom circuits](https://github.com/0xdeenz/bq2/tree/main/packages/circuits), which define the base logic of the protocol. - The [core smart contracts](https://github.com/0xdeenz/bq2/tree/main/packages/contracts), developed in Solidity, and acting as verifiers to enforce this logic. - A [subraph](https://github.com/0xdeenz/bq2-subgraph) used to index events from these smart contracts, and that can be interacted with via the separate [data package](https://github.com/0xdeenz/bq2/tree/main/packages/data). - A series of [TypeScript/JavaScript libraries](https://github.com/0xdeenz/bq2/tree/main/packages/lib) are also provided, enabling developers to easily interact with the protocol and generate and verify all the proofs that power Block Qualified. These have each been released as their separate npm packages, allowing developers to build on top of the protocol. More information on these can be found on each of the links above. Additionally, a [simple frontend](https://github.com/0xdeenz/bq2-site) has been build on React, implementing a demo usecase of the protocol, and can be accessed at: <div style="display:flex; align-items:center; justify-content:center; padding-bottom:15px"> <a href="https://bq2.netlify.app/" target="_blank" aria_label="bq2-site"> bq2.netlify.app </a> </div> ## Technical Reference At the core of Block Qualified is the [Credential Registry](https://github.com/0xdeenz/bq2/blob/main/packages/contracts/contracts/CredentialsRegistry.sol), built to support **any kind of credential types**, each with their own behavior. A credential type defines how a credential operates: the rules that must be followed to obtain them. Users can define the behavior of their own credential types, link them to the registry, and create and obtain different credentials that follow these set behaviors. The [Credential Registry](https://github.com/0xdeenz/bq2/blob/main/packages/contracts/contracts/CredentialsRegistry.sol) keeps track of all credential states, which are represented by Merkle trees: - The **grade group**, composed of the [grade commitments](https://deenz.gitbook.io/bq2/technical-reference/circuits#grade-tree-inclusion) of all the users that attempted to gain the credential, regardless of whether they obtained it. - The **credentials group**, composed of the [Semaphore identity commitments](http://semaphore.appliedzkp.org/docs/guides/identities) of all the users that obtained the credential. - THe **no-credentials group**, composed of the [Semaphore identity commitments](http://semaphore.appliedzkp.org/docs/guides/identities) of all the users that did **not** obtain the credential. Block Qualified has **native support for the [Test Credential](https://github.com/0xdeenz/bq2/blob/main/packages/contracts/contracts/managers/TestCredentialManager.sol)**. Each test credential contains two distinct components, each forming a Merkle tree formed with the SNARK-friendly [Poseidon](https://www.poseidon-hash.info/) hash function: <p align="center"> <img src="https://raw.githubusercontent.com/0xdeenz/bq2/main/docs/technical-reference/test-diagram.png" width=100% /> </p> - A **multiple choice component**, where the answer to each question is part of a given finite set. The grade for this component is only awarded if the user gets all the answers right. - An **open answer component**, where the answer to each question can be any value. The leaves being the [_keccak256_ hashes](https://github.com/0xdeenz/bq2/blob/main/packages/lib/src/helpers/hash.ts) of the answers, made compatible with the SNARK scalar modulus. The grade for this component is awarded incrementally per answer that the user gets right. When the user's grade is over the defined `minimumGrade` ,they have gained the test credential, and their identity commitment gets added to the ***credentials group***. Otherwise, their identity commitment gets added to the ***no-credentials group***. This is all done inside of the zk-proof via the [Test circuit](https://github.com/0xdeenz/bq2/blob/main/packages/circuits/circuits/test.circom) -- the [Test Credential](https://github.com/0xdeenz/bq2/blob/main/packages/contracts/contracts/managers/TestCredentialManager.sol) smart contract then enforces the correctness of the proof. After users have attempted a credential, they can: - Use the [Semaphore circuit](http://semaphore.appliedzkp.org/docs/technical-reference/circuits) to signal anonymously with a zero-knowledge proof that they are a part of the credentials/no-credentials group. - Use the [Grade Claim circuit](https://github.com/0xdeenz/bq2/blob/main/packages/circuits/circuits/grade_claim.circom) to signal anonymously with a zero-knowledge proof that they obtained a grade that is greater than or equal to a certain threshold. Users earn these credentials by sending transactions to the [Credential Registry](https://github.com/0xdeenz/bq2/blob/main/packages/contracts/contracts/CredentialsRegistry.sol). In order to increase privacy, and since these transactions do not require a direct interaction from the user (like when managing funds), a **transaction relayer** is used. This way, all transactions originate from the same address, so tracing them back to a user becomes a harder task. The [Defender Relay](https://docs.openzeppelin.com/defender/relay) service by OpenZeppelin is used to this end. #### You can read more about the technical implementation on the [documentation](https://deenz.gitbook.io/bq2/technical-reference/block-qualified-tests). ## Possible Next Steps - Launching a **platform** integrating Block Qualified. We will look into again integrating it within [useWeb3](https://www.useweb3.xyz/) with the goal of gathering feedback and testing the protocol against real users. - Studying the possibility of implementing **newer zk-protocols**. Particularly [Semacaulk](https://github.com/geometryresearch/semacaulk), which promises to greatly reduce transaction costs regarding anonymous signaling. - Implementing **other credential types**, that can extend the native functionality of the protocol beyond the multiple choice/open answer dynamic. ## Additional Resources #### You can check this 3-minute [demo walkthrough](https://youtu.be/n0m2aHLhoXs) highlighting the main functionalities. This demo has been deployed on the Polygon Mumbai testnet network. If you wish to interact directly with the protocol, you can get yourself some testnet funds at [this faucet](https://mumbaifaucet.com/) or [this faucet](https://faucet.polygon.technology/). #### Deployed Contracts | Contract | Mumbai | | -------- | ------ | | [CredentialsRegistry.sol](../packages/contracts/contracts/CredentialsRegistry.sol) | [0x5A14...14C4](https://mumbai.polygonscan.com/address/0x5A140303E92da80BF96a734fd777957fF02714C4) | | [TestCredentialManager.sol](../packages/contracts/contracts/managers/TestCredentialManager.sol) | [0x043c...1cee](https://mumbai.polygonscan.com/address/0x043c69abf15d154cf0Ffc482f8d63eE7874e1cee) | | [LegacyCredentialManager.sol](../packages/contracts/contracts/managers/LegacyCredentialManager.sol) | [0x7747...72C7](https://mumbai.polygonscan.com/address/0x77479918eA3962f8a1EfCc578520582778E272C7) | | [GradeClaimVerifier.sol](../packages/contracts/contracts/base/GradeClaimVerifier.sol) | [0x987B...4eb1](https://mumbai.polygonscan.com/address/0x987B9432B78f1A26490f88D8F972c0a2c46C4eb1) | | [TestVerifier.sol](../packages/contracts/contracts/managers/verifiers/TestVerifier.sol) | [0xA868...f610](https://mumbai.polygonscan.com/address/0xA8687a68c919aB5bAcB039Dd656dA8b2c4DEf610) | | [PoseidonT4.sol](../packages/contracts/contracts/libs/Poseidon.sol) | [0xc5031...Aa62](https://mumbai.polygonscan.com/address/0xc50311C8811B9a19f41EB4B121E3023966BAAa62) | #### Inherited Contracts | Contract | Mumbai | | -------- | ------ | | [SemaphoreVerifier.sol](https://github.com/semaphore-protocol/semaphore/blob/main/packages/contracts/contracts/base/SemaphoreVerifier.sol) | [0x5f4e...5a49](https://mumbai.polygonscan.com/address/0x5f4edC58142f4395D1D536e793137A0252dA5a49) | | [PoseidonT3.sol](../packages/contracts/contracts/libs/Poseidon.sol) | [0x181B...1648](https://mumbai.polygonscan.com/address/0x181B7f34538cE3BceC68597d4A212aB3f7881648) | ## Acknowledgements A huge shoutout to the folks over at the Ethereum Foundation's [Privacy and Scaling Explorations](https://twitter.com/PrivacyScaling) team for making this possible. Big thanks go to Andy for helping in the onboarding process and all throughout the project, and to [cedoor](https://twitter.com/cedoor_) for providing the clearest answers to even the dumbest of questions on the [Discord](https://discord.com/invite/6mSdGHnstH). A final thank you note to [Wesley](https://twitter.com/wslyvh) for originally telling me about the grant, and letting me deploy and implement the original version onto his website [useWeb3](https://academy.useweb3.xyz/).