Skip to content

Commit

Permalink
refactor(contracts): implement interfaces and factory deployment of m…
Browse files Browse the repository at this point in the history
…p/tally/subsidy
  • Loading branch information
ctrlc03 committed Jan 4, 2024
1 parent 94eff87 commit b9fee47
Show file tree
Hide file tree
Showing 20 changed files with 261 additions and 166 deletions.
74 changes: 31 additions & 43 deletions contracts/contracts/MACI.sol
Original file line number Diff line number Diff line change
@@ -1,28 +1,19 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;

import { Poll } from "./Poll.sol";
import { PollFactory } from "./PollFactory.sol";
import { MessageProcessor } from "./MessageProcessor.sol";
import { MessageProcessorFactory } from "./MessageProcessorFactory.sol";
import { Tally } from "./Tally.sol";
import { TallyFactory } from "./TallyFactory.sol";
import { Subsidy } from "./Subsidy.sol";
import { SubsidyFactory } from "./SubsidyFactory.sol";
import { IPollFactory } from "./interfaces/IPollFactory.sol";
import { IMessageProcessorFactory } from "./interfaces/IMPFactory.sol";
import { ITallySubsidyFactory } from "./interfaces/ITallySubsidyFactory.sol";
import { InitialVoiceCreditProxy } from "./initialVoiceCreditProxy/InitialVoiceCreditProxy.sol";
import { SignUpGatekeeper } from "./gatekeepers/SignUpGatekeeper.sol";
import { AccQueue, AccQueueQuinaryBlankSl } from "./trees/AccQueue.sol";
import { IMACI } from "./interfaces/IMACI.sol";
import { Params } from "./utilities/Params.sol";
import { DomainObjs } from "./utilities/DomainObjs.sol";
import { TopupCredit } from "./TopupCredit.sol";
import { SnarkCommon } from "./crypto/SnarkCommon.sol";
import { SnarkConstants } from "./crypto/SnarkConstants.sol";
import { Hasher } from "./crypto/Hasher.sol";
import { Utilities } from "./utilities/Utilities.sol";
import { Verifier } from "./crypto/Verifier.sol";
import { VkRegistry } from "./VkRegistry.sol";
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { IMACI } from "./interfaces/IMACI.sol";

/// @title MACI - Minimum Anti-Collusion Infrastructure Version 1
/// @notice A contract which allows users to sign up, and deploy new polls
Expand All @@ -47,7 +38,7 @@ contract MACI is IMACI, Params, Utilities, Ownable {
uint256 public nextPollId;

/// @notice A mapping of poll IDs to Poll contracts.
mapping(uint256 => Poll) public polls;
mapping(uint256 => address) public polls;

/// @notice The number of signups
uint256 public override numSignUps;
Expand All @@ -59,16 +50,16 @@ contract MACI is IMACI, Params, Utilities, Ownable {
TopupCredit public topupCredit;

/// @notice Factory contract that deploy a Poll contract
PollFactory public pollFactory;
IPollFactory public pollFactory;

/// @notice Factory contract that deploy a MessageProcessor contract
MessageProcessorFactory public messageProcessorFactory;
IMessageProcessorFactory public messageProcessorFactory;

/// @notice Factory contract that deploy a Tally contract
TallyFactory public tallyFactory;
ITallySubsidyFactory public tallyFactory;

/// @notice Factory contract that deploy a Subsidy contract
SubsidyFactory public subsidyFactory;
ITallySubsidyFactory public subsidyFactory;

/// @notice The state AccQueue. Represents a mapping between each user's public key
/// and their voice credit balance.
Expand All @@ -88,14 +79,8 @@ contract MACI is IMACI, Params, Utilities, Ownable {

// Events
event SignUp(uint256 _stateIndex, PubKey _userPubKey, uint256 _voiceCreditBalance, uint256 _timestamp);
event DeployPoll(
uint256 _pollId,
address _pollAddr,
PubKey _pubKey,
address _mpAddr,
address _tallyAddr,
address _subsidyAddr
);
event DeployPoll(uint256 _pollId, address _pollAddr, PubKey _pubKey, address _mpAddr, address _tallyAddr);
event DeploySubsidy(address _subsidyAddr);

/// @notice Only allow a Poll contract to call the modified function.
modifier onlyPoll(uint256 _pollId) {
Expand All @@ -119,10 +104,10 @@ contract MACI is IMACI, Params, Utilities, Ownable {
/// @param _initialVoiceCreditProxy The InitialVoiceCreditProxy contract
/// @param _stateTreeDepth The depth of the state tree
constructor(
PollFactory _pollFactory,
MessageProcessorFactory _messageProcessorFactory,
TallyFactory _tallyFactory,
SubsidyFactory _subsidyFactory,
IPollFactory _pollFactory,
IMessageProcessorFactory _messageProcessorFactory,
ITallySubsidyFactory _tallyFactory,
ITallySubsidyFactory _subsidyFactory,
SignUpGatekeeper _signUpGatekeeper,
InitialVoiceCreditProxy _initialVoiceCreditProxy,
TopupCredit _topupCredit,
Expand Down Expand Up @@ -205,14 +190,16 @@ contract MACI is IMACI, Params, Utilities, Ownable {
/// @param _coordinatorPubKey The coordinator's public key
/// @param _verifier The Verifier Contract
/// @param _vkRegistry The VkRegistry Contract
/// @param useSubsidy If true, the Poll will use the Subsidy contract
/// @return pollAddr a new Poll contract address
function deployPoll(
uint256 _duration,
MaxValues memory _maxValues,
TreeDepths memory _treeDepths,
PubKey memory _coordinatorPubKey,
Verifier _verifier,
VkRegistry _vkRegistry
address _verifier,
address _vkRegistry,
bool useSubsidy
) public onlyOwner returns (address pollAddr) {
uint256 pollId = nextPollId;

Expand All @@ -233,31 +220,32 @@ contract MACI is IMACI, Params, Utilities, Ownable {
uint24(STATE_TREE_ARITY) ** _treeDepths.intStateTreeDepth
);

Poll p = pollFactory.deploy(
address _owner = owner();

address p = pollFactory.deploy(
_duration,
_maxValues,
_treeDepths,
batchSizes,
_coordinatorPubKey,
this,
topupCredit,
owner()
_owner
);

MessageProcessor mp = messageProcessorFactory.deploy(_verifier, _vkRegistry, p);
address mp = messageProcessorFactory.deploy(_verifier, _vkRegistry, p, _owner);
address tally = tallyFactory.deploy(_verifier, _vkRegistry, p, mp, _owner);

Tally tally = tallyFactory.deploy(_verifier, _vkRegistry, p, mp);

Subsidy subsidy = subsidyFactory.deploy(_verifier, _vkRegistry, p, mp);
if (useSubsidy) {
address subsidy = subsidyFactory.deploy(_verifier, _vkRegistry, p, mp, _owner);
emit DeploySubsidy(subsidy);
}

polls[pollId] = p;

pollAddr = address(p);
address mpAddr = address(mp);
address tallyAddr = address(tally);
address subsidyAddr = address(subsidy);

emit DeployPoll(pollId, pollAddr, _coordinatorPubKey, mpAddr, tallyAddr, subsidyAddr);
emit DeployPoll(pollId, pollAddr, _coordinatorPubKey, mp, tally);
}

/// @notice Allow Poll contracts to merge the state subroots
Expand All @@ -283,7 +271,7 @@ contract MACI is IMACI, Params, Utilities, Ownable {
/// @notice Get the Poll details
/// @param _pollId The identifier of the Poll to retrieve
/// @return poll The Poll contract object
function getPoll(uint256 _pollId) public view returns (Poll poll) {
function getPoll(uint256 _pollId) public view returns (address poll) {
if (_pollId >= nextPollId) revert PollDoesNotExist(_pollId);
poll = polls[_pollId];
}
Expand Down
25 changes: 12 additions & 13 deletions contracts/contracts/MessageProcessor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,17 @@ pragma solidity ^0.8.10;
import { AccQueue } from "./trees/AccQueue.sol";
import { IMACI } from "./interfaces/IMACI.sol";
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { Poll } from "./Poll.sol";
import { IPoll } from "./interfaces/IPoll.sol";
import { SnarkCommon } from "./crypto/SnarkCommon.sol";
import { Hasher } from "./crypto/Hasher.sol";
import { CommonUtilities } from "./utilities/Utilities.sol";
import { Verifier } from "./crypto/Verifier.sol";
import { VkRegistry } from "./VkRegistry.sol";
import { IVerifier } from "./interfaces/IVerifier.sol";
import { IVkRegistry } from "./interfaces/IVkRegistry.sol";

/// @title MessageProcessor
/// @dev MessageProcessor is used to process messages published by signup users.
/// It will process message by batch due to large size of messages.
/// After it finishes processing, the sbCommitment will be used for Tally and Subsidy contracts.
contract MessageProcessor is Ownable, SnarkCommon, CommonUtilities, Hasher {
contract MessageProcessor is Ownable, SnarkCommon, Hasher {
/// @notice custom errors
error NoMoreMessages();
error StateAqNotMerged();
Expand All @@ -38,26 +37,26 @@ contract MessageProcessor is Ownable, SnarkCommon, CommonUtilities, Hasher {
/// @notice The commitment to the state and ballot roots
uint256 public sbCommitment;

Poll public poll;
Verifier public verifier;
VkRegistry public vkRegistry;
IPoll public poll;
IVerifier public verifier;
IVkRegistry public vkRegistry;

/// @notice Create a new instance
/// @param _verifier The Verifier contract address
/// @param _vkRegistry The VkRegistry contract address
/// @param _poll The Poll contract address
constructor(Verifier _verifier, VkRegistry _vkRegistry, Poll _poll) {
verifier = _verifier;
vkRegistry = _vkRegistry;
poll = _poll;
constructor(address _verifier, address _vkRegistry, address _poll) {
verifier = IVerifier(_verifier);
vkRegistry = IVkRegistry(_vkRegistry);
poll = IPoll(_poll);
}

/// @notice Update the Poll's currentSbCommitment if the proof is valid.
/// @param _newSbCommitment The new state root and ballot root commitment
/// after all messages are processed
/// @param _proof The zk-SNARK proof
function processMessages(uint256 _newSbCommitment, uint256[8] memory _proof) external onlyOwner {
_votingPeriodOver(poll);
// _votingPeriodOver(poll);
// There must be unprocessed messages
if (processingComplete) {
revert NoMoreMessages();
Expand Down
21 changes: 10 additions & 11 deletions contracts/contracts/MessageProcessorFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@ pragma solidity ^0.8.10;
import { Params } from "./utilities/Params.sol";
import { DomainObjs } from "./utilities/DomainObjs.sol";
import { MessageProcessor } from "./MessageProcessor.sol";
import { Poll } from "./Poll.sol";
import { Verifier } from "./crypto/Verifier.sol";
import { VkRegistry } from "./VkRegistry.sol";

/// @title MessageProcessorFactory
/// @notice A factory contract which deploys MessageProcessor contracts.
Expand All @@ -15,15 +12,17 @@ contract MessageProcessorFactory is Params, DomainObjs {
/// @param _verifier Verifier contract
/// @param _vkRegistry VkRegistry contract
/// @param _poll Poll contract
/// @return messageProcessor The deployed MessageProcessor contract
/// @param _owner Owner of the MessageProcessor contract
/// @return messageProcessorAddr The deployed MessageProcessor contract
function deploy(
Verifier _verifier,
VkRegistry _vkRegistry,
Poll _poll
) public returns (MessageProcessor messageProcessor) {
address _verifier,
address _vkRegistry,
address _poll,
address _owner
) public returns (address messageProcessorAddr) {
/// @notice deploy MessageProcessor for this Poll
messageProcessor = new MessageProcessor(_verifier, _vkRegistry, _poll);

return messageProcessor;
MessageProcessor messageProcessor = new MessageProcessor(_verifier, _vkRegistry, _poll);
messageProcessor.transferOwnership(_owner);
messageProcessorAddr = address(messageProcessor);
}
}
10 changes: 4 additions & 6 deletions contracts/contracts/Poll.sol
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;

import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

import { Params } from "./utilities/Params.sol";
import { SnarkCommon } from "./crypto/SnarkCommon.sol";
import { DomainObjs } from "./utilities/DomainObjs.sol";
import { AccQueue, AccQueueQuinaryMaci } from "./trees/AccQueue.sol";
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { Verifier } from "./crypto/Verifier.sol";
import { EmptyBallotRoots } from "./trees/EmptyBallotRoots.sol";
import { TopupCredit } from "./TopupCredit.sol";
import { Utilities } from "./utilities/Utilities.sol";
import { MessageProcessor } from "./MessageProcessor.sol";

/// @title Poll
/// @notice A Poll contract allows voters to submit encrypted messages
Expand Down
8 changes: 5 additions & 3 deletions contracts/contracts/PollFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ contract PollFactory is Params, DomainObjs {
/// @param _maci The MACI contract interface reference
/// @param _topupCredit The TopupCredit contract
/// @param _pollOwner The owner of the poll
/// @return poll The deployed Poll contract
/// @return pollAddr The deployed Poll contract
function deploy(
uint256 _duration,
MaxValues memory _maxValues,
Expand All @@ -36,7 +36,7 @@ contract PollFactory is Params, DomainObjs {
IMACI _maci,
TopupCredit _topupCredit,
address _pollOwner
) public returns (Poll poll) {
) public returns (address pollAddr) {
/// @notice Validate _maxValues
/// maxVoteOptions must be less than 2 ** 50 due to circuit limitations;
/// it will be packed as a 50-bit value along with other values as one
Expand All @@ -58,7 +58,7 @@ contract PollFactory is Params, DomainObjs {
ExtContracts memory extContracts = ExtContracts({ maci: _maci, messageAq: messageAq, topupCredit: _topupCredit });

// deploy the poll
poll = new Poll(_duration, _maxValues, _treeDepths, _batchSizes, _coordinatorPubKey, extContracts);
Poll poll = new Poll(_duration, _maxValues, _treeDepths, _batchSizes, _coordinatorPubKey, extContracts);

// Make the Poll contract own the messageAq contract, so only it can
// run enqueue/merge
Expand All @@ -68,5 +68,7 @@ contract PollFactory is Params, DomainObjs {
poll.init();

poll.transferOwnership(_pollOwner);

pollAddr = address(poll);
}
}
33 changes: 16 additions & 17 deletions contracts/contracts/Subsidy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,19 @@
pragma solidity ^0.8.10;

import { IMACI } from "./interfaces/IMACI.sol";
import { MessageProcessor } from "./MessageProcessor.sol";
import { IMessageProcessor } from "./interfaces/IMessageProcessor.sol";
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { Poll } from "./Poll.sol";
import { IPoll } from "./interfaces/IPoll.sol";
import { SnarkCommon } from "./crypto/SnarkCommon.sol";
import { Hasher } from "./crypto/Hasher.sol";
import { CommonUtilities } from "./utilities/Utilities.sol";
import { Verifier } from "./crypto/Verifier.sol";
import { VkRegistry } from "./VkRegistry.sol";
import { IVerifier } from "./interfaces/IVerifier.sol";
import { IVkRegistry } from "./interfaces/IVkRegistry.sol";

/// @title Subsidy
/// @notice This contract is used to verify that the subsidy calculations
/// are correct. It is also used to update the subsidy commitment if the
/// proof is valid.
contract Subsidy is Ownable, CommonUtilities, Hasher, SnarkCommon {
contract Subsidy is Ownable, Hasher, SnarkCommon {
uint256 public rbi; // row batch index
uint256 public cbi; // column batch index
// The final commitment to the state and ballot roots
Expand All @@ -33,21 +32,21 @@ contract Subsidy is Ownable, CommonUtilities, Hasher, SnarkCommon {
error RbiTooLarge();
error CbiTooLarge();

Verifier public verifier;
VkRegistry public vkRegistry;
Poll public poll;
MessageProcessor public mp;
IVerifier public verifier;
IVkRegistry public vkRegistry;
IPoll public poll;
IMessageProcessor public mp;

/// @notice Create a new Subsidy contract
/// @param _verifier The Verifier contract
/// @param _vkRegistry The VkRegistry contract
/// @param _poll The Poll contract
/// @param _mp The MessageProcessor contract
constructor(Verifier _verifier, VkRegistry _vkRegistry, Poll _poll, MessageProcessor _mp) {
verifier = _verifier;
vkRegistry = _vkRegistry;
poll = _poll;
mp = _mp;
constructor(address _verifier, address _vkRegistry, address _poll, address _mp) {
verifier = IVerifier(_verifier);
vkRegistry = IVkRegistry(_vkRegistry);
poll = IPoll(_poll);
mp = IMessageProcessor(_mp);
}

/// @notice Update the currentSbCommitment if the proof is valid.
Expand Down Expand Up @@ -93,14 +92,14 @@ contract Subsidy is Ownable, CommonUtilities, Hasher, SnarkCommon {
/// @param _newSubsidyCommitment The new subsidy commitment
/// @param _proof The proof
function updateSubsidy(uint256 _newSubsidyCommitment, uint256[8] memory _proof) external onlyOwner {
_votingPeriodOver(poll);
// _votingPeriodOver(poll);
updateSbCommitment();

(uint8 intStateTreeDepth, , , ) = poll.treeDepths();

uint256 subsidyBatchSize = uint256(treeArity) ** intStateTreeDepth;

(uint256 numSignUps, ) = _poll.numSignUpsAndMessages();
(uint256 numSignUps, ) = poll.numSignUpsAndMessages();

// Require that there are unfinished ballots left
if (rbi * subsidyBatchSize > numSignUps) {
Expand Down
Loading

0 comments on commit b9fee47

Please sign in to comment.