The Mina developer community is full of brilliant, creative and curious people trying to build awesome stuff with ZK. We’re always getting interesting questions about o1js and Mina from developers looking to understand in more detail some API or concept. This is a fantastic feedback loop for the team at o1Labs because it gives us signal about what APIs people are looking at and using and what parts of our codebase need better documentation. We thought it would be interesting to share some of these questions with a broader audience to showcase our awesome Q&A board on Discord and to get developers thinking about advanced topics. Let’s dive into some questions!
Question 1: From a developer's point of view, why bother with recursion?
I love this question because it gets to the heart of programming in zk. Developers from web2 and web3 are used to executing a program in order until the steps are complete. o1js asks developers to write recursive zk proofs in which a single zk proof takes another one or two proofs as input and verifies them as part of its own logic. Recursive proofs are cheap to verify, so by turning two proofs into one recursive proof, you reduce the cost of verifying both proofs by half. This process can be repeated to convert an arbitrary number of proofs into one recursive proof of fixed verification cost. Coming from a web2 or web3 background, it feels unnatural to break a program into separate executable layers. There is a tradeoff that the prover needs to spend additional time creating multiple layers of proofs, and it takes additional thought to lay out the structure of the recursion. So a fair question is, “Why bother with all this”?

Answer
The discord discussion from Las and Gregor is spot on about why developers would want to use this API 🍻.
One reason is that the recursion step can be executed an arbitrary number of times. Using loops in zk can be confusing because code can’t branch like it can with VM stacks. We can’t loop over some steps `while` a condition is met, and we can’t iterate `for` a variable number of steps within a zk circuit. We can encode one step of our program as a zk circuit and then execute a dynamic number of steps. This is particularly useful for programs with unbounded collection inputs. Take Mina, for example. We could prove the correct execution of some number of blocks in a row, but we want to prove the correct execution of every block in the blockchain. Because there is a theoretically infinite number of blocks in the chain, we can’t write a single circuit that will verify all of them in a row. Instead, we use proof recursion to prove one block at a time.
Another reason to use recursion is if multiple parties want to collaborate on one proof with different private inputs. Take, for example, a proof that requires two signatures to unlock some funds. One party cannot produce both signatures, so they can use recursion to collaborate without leaking private data.
This is a great question that many developers will find themselves asking as they learn more about zk programming and o1js.
Question 2: What does `voting_for` in AccountUpdate do?
`AccountUpdate` is a data structure used in Mina programming to interact with accounts on chain. Some elements are intuitive, like accessing an account’s public key or balance. But there are also some esoteric fields like `votingFor` that developers can manipulate, but very few people understand.
This is a pain point that o1Labs is addressing! On our roadmap, you’ll note two projects related to the question asked here: we are improving our documentation and developing a new API for interacting with Mina that is more explicit about what is happening under the hood. These new tools will give developers more confidence in the lesser-known features in o1js.
Answer
It turns out that `votingFor` is a vestigial property on accounts that we included as a potential tool to resolve hard fork disputes but has not been used since the genesis block 🤷♂️. When we executed the Berkeley hard fork in June, it was not contentious. Perhaps `votingFor` will be used in the future for community governance or resolving a hard fork dispute. For now, it is essentially a dummy hash value that isn’t used.
Question 3: What formula does the node use to decide what zkApp transactions to include in the block?
Mina is a gasless blockchain! The killer feature of the Mina blockchain is that computation is all done off chain, so transactions are incredibly cheap and can contain practically unlimited amounts of computation neatly wrapped in a recursive proof. Yet the author of this question noticed that their transactions were not being included compared to other transactions with a lower fee, prompting the question.
Answer
Even though there is no gas, there is a slight variance in the “weight” of, or the time it takes a block producer to produce a snark for each transaction. The weight formula is
`10.26*(# proofs) + 10.08*(# pairs of signatures) + 9.14*(# single signatures)`
So, a transaction containing one proof will take slightly longer to prove than one containing one signature. However, a transaction containing three signatures (one pair, and one single, since pairs can be more efficiently SNARKed) would be more expensive than a transaction containing only one proof. The weights listed above are defaults, set by o1js, discovered through testing. Block producers can set their own values, and ultimately decide which transactions to work on. The network may not select a transaction with a higher fixed-fee if it includes more proofs and signatures than another transaction, even with a lower fee!
It just so happens that we are currently working on a new API to set transaction fee per snark cost. Check out PR#1968 which should be merged, or merging shortly after this post goes live.
Wrapping Up
We hope you found this deep dive into three community questions interesting! If you want to follow-up and join the conversation, swing by #zkapps-developers on discord!
Links to the original Discord chats:
(1. link, 2. link, 3. link)