From Barry: For MACI topups i think its best to have a smart contract que that uses the (batch deposit mech) and then have the cooridnator produce a ZKP that they have added the balance to the leaf they specified. If they refuse to add the deposit the round stops and after a deadline passes the users are able to wtihdraw their funds. We should consider this for malicious coordinators trying to lock users funds inside.
Let's say I sign up to MACI and use all my voice credits. Now I have to sign up again. There's no way to put more voice credits to this leaf. For some apps, this is a problem. For QHP, we want to give users their voice credits back every week.
So we need a way to top-up voice credits.
The voice credit balance is part of the user's state leaf. Each state leaf is a hash of the following information:
Like the UpdateStateTree
circuit, we could have a snark which:
The contract will verify this proof and update the state root if it is valid.
There can be another circuit which updates a batch of state leaves in a single transaction.
The downside to this solution is that it requires the coordinator to do a lot of computationally intensive work, and to pay a lot of gas to execute the transactions.
The upside is that no changes are needed to the current architecture.
Estimate implementation time (full-time): 1 week
barryWhiteHat we could charge a fee to allow cover proving / gas costs.
This solution seeks to reduce the proof-generation computational load on the coordinator, but it requires a deep change to the MACI architecture.
We have a new contract storage mapping which which associates state leaf indices with encrypted and salted voice credit balances.
The encryption keys and salt values are only known to the coordinator. Each key may be an ECDH key generated using the coordinator's public key and the user's private key, but it is still clear whether the user should use a separate private key from the one they use to sign commands, or if they should use the same one.
To update a user's voice credit balance, the coordinator supplies a snark proof of the following:
If the proof is valid, the contract function stores the new ciphertext in the mapping.
This can also be done in batches.
A change is required to the UpdateStateTree
circuit.
Each state leaf no longer stores the voice credit balance.
The UpdateStateTree
circuit decrypts the encrypted balance, updates the vote option tree, and modifies the voice credit balance depending on how the user spent their votes. It then encrypts and outputs the new voice credit balance, and updates the mapping.
The downside to this approach is that it increases complexity of the system. Moreover, each invocation of batchProcessMessage()
will be more expensive as it has to update the storage mapping (5k gas per user).
The upside is that voice credit top-ups are now less expensive. Furthermore, it is possible to (publicly) give all users the same number of voice credits by storing the same ciphertext to all mapping indices.
Estimate implementation time (full-time): 3 weeks
Barry: i like having seperate trees one for balance and another that says how much has been spent. so i can spend total_deposit - already_spent
where already_spent
is stored in the leaf and total_deposit
is a append only tree that maps (leaf_index -> amount)