Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(contracts): relay messages #2002

Merged
merged 1 commit into from
Jan 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 14 additions & 10 deletions packages/cli/ts/commands/deployPoll.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export const deployPoll = async ({
gatekeeperAddress,
voiceCreditProxyAddress,
initialVoiceCreditsBalance,
relayers = [],
signer,
quiet = true,
useQuadraticVoting = false,
Expand Down Expand Up @@ -123,18 +124,21 @@ export const deployPoll = async ({
try {
// deploy the poll contract via the maci contract
const tx = await maciContract.deployPoll(
pollDuration,
{
intStateTreeDepth,
voteOptionTreeDepth,
duration: pollDuration,
treeDepths: {
intStateTreeDepth,
voteOptionTreeDepth,
},
messageBatchSize,
coordinatorPubKey: unserializedKey.asContractParam(),
verifier: verifierContractAddress,
vkRegistry,
mode: useQuadraticVoting ? EMode.QV : EMode.NON_QV,
gatekeeper: signupGatekeeperContractAddress,
initialVoiceCreditProxy: initialVoiceCreditProxyAddress,
relayers,
},
messageBatchSize,
unserializedKey.asContractParam(),
verifierContractAddress,
vkRegistry,
useQuadraticVoting ? EMode.QV : EMode.NON_QV,
signupGatekeeperContractAddress,
initialVoiceCreditProxyAddress,
{ gasLimit: 10000000 },
);

Expand Down
2 changes: 2 additions & 0 deletions packages/cli/ts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ program
true,
)
.option("-x, --maci-address <maciAddress>", "the MACI contract address")
.option("-ra, --relayers <relayers>", "the relayer addresses", (value) => value.split(",").map((item) => item.trim()))
.option("-q, --quiet <quiet>", "whether to print values to the console", (value) => value === "true", false)
.option("-r, --rpc-provider <provider>", "the rpc provider URL")
.action(async (cmdObj) => {
Expand All @@ -203,6 +204,7 @@ program
coordinatorPubkey: cmdObj.pubkey,
maciAddress: cmdObj.maciAddress,
vkRegistryAddress: cmdObj.vkRegistryAddress,
relayers: cmdObj.relayers,
quiet: cmdObj.quiet,
useQuadraticVoting: cmdObj.useQuadraticVoting,
signer,
Expand Down
5 changes: 5 additions & 0 deletions packages/cli/ts/utils/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,11 @@ export interface DeployPollArgs {
*/
signer: Signer;

/**
* The relayer addresses
*/
relayers?: string[];

/**
* The MACI contract address
*/
Expand Down
74 changes: 40 additions & 34 deletions packages/contracts/contracts/MACI.sol
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,29 @@ contract MACI is IMACI, DomainObjs, Params, Hasher {
address messageProcessor;
address tally;
}
/// @notice A struct holding the params for poll deployment
struct DeployPollArgs {
/// @param duration How long should the Poll last for
uint256 duration;
/// @param treeDepths The depth of the Merkle trees
TreeDepths treeDepths;
/// @param messageBatchSize The message batch size
uint8 messageBatchSize;
/// @param coordinatorPubKey The coordinator's public key
PubKey coordinatorPubKey;
/// @param verifier The Verifier Contract
address verifier;
/// @param vkRegistry The VkRegistry Contract
address vkRegistry;
/// @param mode Voting mode
Mode mode;
/// @param gatekeeper The gatekeeper contract
address gatekeeper;
/// @param initialVoiceCreditProxy The initial voice credit proxy contract
address initialVoiceCreditProxy;
/// @param relayer The message relayer (optional)
address[] relayers;
}

// Events
event SignUp(uint256 _stateIndex, uint256 _timestamp, uint256 indexed _userPubKeyX, uint256 indexed _userPubKeyY);
Expand Down Expand Up @@ -148,26 +171,8 @@ contract MACI is IMACI, DomainObjs, Params, Hasher {
}

/// @notice Deploy a new Poll contract.
/// @param _duration How long should the Poll last for
/// @param _treeDepths The depth of the Merkle trees
/// @param _messageBatchSize The message batch size
/// @param _coordinatorPubKey The coordinator's public key
/// @param _verifier The Verifier Contract
/// @param _vkRegistry The VkRegistry Contract
/// @param _mode Voting mode
/// @param _gatekeeper The gatekeeper contract
/// @param _initialVoiceCreditProxy The initial voice credit proxy contract
function deployPoll(
uint256 _duration,
TreeDepths memory _treeDepths,
uint8 _messageBatchSize,
PubKey memory _coordinatorPubKey,
address _verifier,
address _vkRegistry,
Mode _mode,
address _gatekeeper,
address _initialVoiceCreditProxy
) public virtual {
/// @param args The deploy poll args
function deployPoll(DeployPollArgs calldata args) public virtual {
// cache the poll to a local variable so we can increment it
uint256 pollId = nextPollId;

Expand All @@ -178,39 +183,40 @@ contract MACI is IMACI, DomainObjs, Params, Hasher {
}

// check coordinator key is a valid point on the curve
if (!CurveBabyJubJub.isOnCurve(_coordinatorPubKey.x, _coordinatorPubKey.y)) {
if (!CurveBabyJubJub.isOnCurve(args.coordinatorPubKey.x, args.coordinatorPubKey.y)) {
revert InvalidPubKey();
}

uint256 voteOptionTreeDepth = _treeDepths.voteOptionTreeDepth;
uint256 voteOptionTreeDepth = args.treeDepths.voteOptionTreeDepth;

ExtContracts memory extContracts = ExtContracts({
maci: IMACI(address(this)),
verifier: IVerifier(_verifier),
vkRegistry: IVkRegistry(_vkRegistry),
gatekeeper: ISignUpGatekeeper(_gatekeeper),
initialVoiceCreditProxy: IInitialVoiceCreditProxy(_initialVoiceCreditProxy)
verifier: IVerifier(args.verifier),
vkRegistry: IVkRegistry(args.vkRegistry),
gatekeeper: ISignUpGatekeeper(args.gatekeeper),
initialVoiceCreditProxy: IInitialVoiceCreditProxy(args.initialVoiceCreditProxy)
});

address p = pollFactory.deploy(
_duration,
_treeDepths,
_messageBatchSize,
_coordinatorPubKey,
args.duration,
args.treeDepths,
args.messageBatchSize,
args.coordinatorPubKey,
extContracts,
emptyBallotRoots[voteOptionTreeDepth - 1],
pollId
pollId,
args.relayers
);

address mp = messageProcessorFactory.deploy(_verifier, _vkRegistry, p, msg.sender, _mode);
address tally = tallyFactory.deploy(_verifier, _vkRegistry, p, mp, msg.sender, _mode);
address mp = messageProcessorFactory.deploy(args.verifier, args.vkRegistry, p, msg.sender, args.mode);
address tally = tallyFactory.deploy(args.verifier, args.vkRegistry, p, mp, msg.sender, args.mode);

// store the addresses in a struct so they can be returned
PollContracts memory pollAddr = PollContracts({ poll: p, messageProcessor: mp, tally: tally });

polls[pollId] = pollAddr;

emit DeployPoll(pollId, _coordinatorPubKey.x, _coordinatorPubKey.y, _mode);
emit DeployPoll(pollId, args.coordinatorPubKey.x, args.coordinatorPubKey.y, args.mode);
}

/// @inheritdoc IMACI
Expand Down
2 changes: 1 addition & 1 deletion packages/contracts/contracts/MessageProcessorFactory.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
pragma solidity ^0.8.20;

import { Params } from "./utilities/Params.sol";
import { DomainObjs } from "./utilities/DomainObjs.sol";
Expand Down
54 changes: 49 additions & 5 deletions packages/contracts/contracts/Poll.sol
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,12 @@ contract Poll is Params, Utilities, SnarkCommon, IPoll {
/// @notice Poll state tree for anonymous joining
LazyIMTData public pollStateTree;

/// @notice IPFS hashes of messages batches
bytes32[] public ipfsHashes;

/// @notice Relayer address
mapping(address => bool) public relayers;

/// @notice The hash of a blank state leaf
uint256 internal constant BLANK_STATE_LEAF_HASH =
uint256(6769006970205099520508948723718471724660867171122235270773600567925038008762);
Expand All @@ -103,6 +109,7 @@ contract Poll is Params, Utilities, SnarkCommon, IPoll {
error BatchHashesAlreadyPadded();
error UserAlreadyJoined();
error InvalidPollProof();
error NotRelayer();

event PublishMessage(Message _message, PubKey _encPubKey);
event MergeState(uint256 indexed _stateRoot, uint256 indexed _numSignups);
Expand Down Expand Up @@ -133,7 +140,8 @@ contract Poll is Params, Utilities, SnarkCommon, IPoll {
PubKey memory _coordinatorPubKey,
ExtContracts memory _extContracts,
uint256 _emptyBallotRoot,
uint256 _pollId
uint256 _pollId,
address[] memory _relayers
) payable {
// check that the coordinator public key is valid
if (!CurveBabyJubJub.isOnCurve(_coordinatorPubKey.x, _coordinatorPubKey.y)) {
Expand All @@ -160,6 +168,14 @@ contract Poll is Params, Utilities, SnarkCommon, IPoll {
emptyBallotRoot = _emptyBallotRoot;
// store the poll id
pollId = _pollId;
// set relayers
for (uint256 index = 0; index < _relayers.length; ) {
relayers[_relayers[index]] = true;

unchecked {
index++;
}
}

unchecked {
numMessages++;
Expand Down Expand Up @@ -189,11 +205,18 @@ contract Poll is Params, Utilities, SnarkCommon, IPoll {
_;
}

/// @notice A modifier that causes the function to revert if the batch hashes is padded
modifier isNotPadded() {
if (isBatchHashesPadded) revert BatchHashesAlreadyPadded();
_;
}

/// @notice A modifier that causes the function to revert if the caller is not a relayer
modifier onlyRelayer() {
if (!relayers[msg.sender]) revert NotRelayer();
_;
}

/// @notice A modifier that causes the function to revert if the voting period is
/// over
modifier isWithinVotingDeadline() virtual {
Expand Down Expand Up @@ -228,6 +251,30 @@ contract Poll is Params, Utilities, SnarkCommon, IPoll {
emit PublishMessage(_message, _encPubKey);
}

/// @inheritdoc IPoll
function relayMessagesBatch(
0xmad marked this conversation as resolved.
Show resolved Hide resolved
uint256[] calldata _messageHashes,
Dismissed Show dismissed Hide dismissed
ctrlc03 marked this conversation as resolved.
Show resolved Hide resolved
bytes32 _ipfsHash
Dismissed Show dismissed Hide dismissed
) public virtual isWithinVotingDeadline onlyRelayer {
uint256 length = _messageHashes.length;

unchecked {
numMessages += length;
}

for (uint256 index = 0; index < length; ) {
updateChainHash(_messageHashes[index]);

unchecked {
index++;
}
}

ipfsHashes.push(_ipfsHash);

emit IpfsHashAdded(_ipfsHash);
}

/// @notice compute and update current message chain hash
/// @param messageHash hash of the current message
function updateChainHash(uint256 messageHash) internal {
Expand All @@ -250,10 +297,7 @@ contract Poll is Params, Utilities, SnarkCommon, IPoll {
isBatchHashesPadded = true;
}

/// @notice submit a message batch
/// @dev Can only be submitted before the voting deadline
/// @param _messages the messages
/// @param _encPubKeys the encrypted public keys
/// @inheritdoc IPoll
function publishMessageBatch(Message[] calldata _messages, PubKey[] calldata _encPubKeys) public virtual {
if (_messages.length != _encPubKeys.length) {
revert InvalidBatchLength();
Expand Down
6 changes: 4 additions & 2 deletions packages/contracts/contracts/PollFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ contract PollFactory is Params, DomainObjs, IPollFactory {
DomainObjs.PubKey calldata _coordinatorPubKey,
Params.ExtContracts calldata _extContracts,
uint256 _emptyBallotRoot,
uint256 _pollId
uint256 _pollId,
Dismissed Show dismissed Hide dismissed
address[] calldata _relayers
Dismissed Show dismissed Hide dismissed
) public virtual returns (address pollAddr) {
// deploy the poll
Poll poll = new Poll(
Expand All @@ -32,7 +33,8 @@ contract PollFactory is Params, DomainObjs, IPollFactory {
_coordinatorPubKey,
_extContracts,
_emptyBallotRoot,
_pollId
_pollId,
_relayers
);

pollAddr = address(poll);
Expand Down
2 changes: 1 addition & 1 deletion packages/contracts/contracts/TallyFactory.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
pragma solidity ^0.8.20;

import { Tally } from "./Tally.sol";
import { ITallyFactory } from "./interfaces/ITallyFactory.sol";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
pragma solidity ^0.8.20;

import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
pragma solidity ^0.8.20;

import { HatsGatekeeperBase } from "./HatsGatekeeperBase.sol";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
pragma solidity ^0.8.20;

import { HatsGatekeeperBase } from "./HatsGatekeeperBase.sol";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
pragma solidity ^0.8.20;

/// @title IEAS
/// @notice An interface to the EAS contract.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
pragma solidity ^0.8.20;

/// @title IHats
/// @notice Minimal interface for the Hats Protocol contract
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
pragma solidity ^0.8.20;

/// @title Semaphore contract interface.
interface ISemaphore {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
pragma solidity ^0.8.20;

/// @title IInitialVoiceCreditProxy
/// @notice InitialVoiceCreditProxy interface
Expand Down
2 changes: 1 addition & 1 deletion packages/contracts/contracts/interfaces/IMPFactory.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
pragma solidity ^0.8.20;

import { DomainObjs } from "../utilities/DomainObjs.sol";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
pragma solidity ^0.8.20;

/// @title IMessageProcessor
/// @notice MessageProcessor interface
Expand Down
Loading
Loading