<aside> ⚠️ All of this is written by me and has not been reviewed. So most of it is just my own interpretation and could be wrong. If you think something is wrong or you have doubts, please comment or message on Discord
</aside>
Let’s start by going into the /contracts
directory and try to run the tests. I usually run everything in a Docker container where I have Rust installed and some extra things I usually need. Here’s what I was missing for Summa.
apt-get install -y libclang-dev
cargo install --version 0.2.23 svm-rs && svm install 0.8.20 && solc --version
cd contracts && npm i
npx hardhat test
I also like to write my tests with Foundry, so I setup Foundry. See here if you need to install it. I think the easiest way is to just call forge init
and then adapt with git if it messed up some of your files 😄 Here it should only modify the README, so you can
forge init --no-git --no-commit --force
git checkout -- README.md
Let me know if you have issues with something, maybe I can (try to) help.
Let’s start with the VerifyingKey contract because it’s needed for the other contracts.
It’s created in gen_verifier.rs and is based on halo2_solidity_verifier which is written by PSE.
The key is going to store all the needed data to verify the circuit: root of unity (omega), elliptic curve points, permutations, …
It’s based on the universal ProvingKey generated during a “Powers of Tau ceremony”. This file holds all the values needed for KZG commitments (”Structured/Common Reference String”) and was generated through multiparty computation and is supposed to be secure 😊
The keys are generated in generate_setup_artifacts. You can take a look at VerifyingKey struct, and see how it’s generated in keygen_vk.
Back to our VerifyingKey contract. It is generated from that VerifyingKey and adapted for Solidity so that we can have all the values we need to perform verification on the EVM. The generate_vk function is called and fills the solidity template with the values from our circuit.
Now we take a quick look at the actual contract to see how it’s organised. It’s really easy to read, all the values are organised nicely, and a comment indicates what the value reprensents. The mstore
instruction is used to store all values in memory and then the memory, and then we return all that memory as the code of the contract.
That way we know exactly what our contract code will be and we will easily be able to fetch the values.
Ok I think that’s all we need, it’s probably already too much details 😁
I’m not going to spend too much time on Summa.sol so I can focus more on the Verifier contracts. You can find a bit of documentation on Summa’s Gitbook.
There is a full flow in /backend/examples/summa_solvency_flow.rs
where we can see how the contracts are being used, but we’ll come back to it later.