From 7c4a807da5f7467973823203f0a6cb2d1ca0c129 Mon Sep 17 00:00:00 2001 From: Koh Wei Jie Date: Wed, 30 Sep 2020 11:24:55 +0800 Subject: [PATCH] Revert "wip" This reverts commit 6da2b2946e076e1cff32af8b66530d8fc6169a4a. --- .../ts/__tests__/BatchUpdateStateTree.test.ts | 5 +- circuits/ts/__tests__/UpdateStateTree.test.ts | 7 +- cli/README.md | 12 +- cli/ts/publish.ts | 126 +++++++-------- cli/ts/signUp.ts | 143 ------------------ 5 files changed, 66 insertions(+), 227 deletions(-) diff --git a/circuits/ts/__tests__/BatchUpdateStateTree.test.ts b/circuits/ts/__tests__/BatchUpdateStateTree.test.ts index 0798945e3c..2933c43ff1 100644 --- a/circuits/ts/__tests__/BatchUpdateStateTree.test.ts +++ b/circuits/ts/__tests__/BatchUpdateStateTree.test.ts @@ -51,6 +51,8 @@ describe('State tree root update verification circuit', () => { 'prod/batchUpdateStateTree_small.circom' ) + // Sign up the user + maciState.signUp(user.pubKey, initialVoiceCreditBalance) }) it('BatchUpdateStateTree should produce the correct state root from a partially filled batch', async () => { @@ -68,8 +70,7 @@ describe('State tree root update verification circuit', () => { const sharedKey = Keypair.genEcdhSharedKey(user.privKey, coordinator.pubKey) const message = command.encrypt(signature, sharedKey) - // Sign up and publish - maciState.signUp(user.pubKey, initialVoiceCreditBalance, message, user.pubKey) + maciState.publishMessage(message, user.pubKey) const randomStateLeaf = StateLeaf.genRandomLeaf() diff --git a/circuits/ts/__tests__/UpdateStateTree.test.ts b/circuits/ts/__tests__/UpdateStateTree.test.ts index 9263bc3cb3..a3a2e5db90 100644 --- a/circuits/ts/__tests__/UpdateStateTree.test.ts +++ b/circuits/ts/__tests__/UpdateStateTree.test.ts @@ -61,8 +61,11 @@ describe('State tree root update verification circuit', () => { beforeAll(async () => { circuit = await compileAndLoadCircuit('test/updateStateTree_test.circom') - // Sign up the user and publish a message - maciState.signUp(user.pubKey, initialVoiceCreditBalance, message, user.pubKey) + // Sign up the user + maciState.signUp(user.pubKey, initialVoiceCreditBalance) + + // Publish a message + maciState.publishMessage(message, user.pubKey) // Generate circuit inputs circuitInputs = maciState.genUpdateStateTreeCircuitInputs(0) diff --git a/cli/README.md b/cli/README.md index c075a757c4..f1a675582b 100644 --- a/cli/README.md +++ b/cli/README.md @@ -130,14 +130,6 @@ Fields that the user has to set: | Prompt for the user's Ethereum private key | `-dp` or `--prompt-for-eth-privkey` | If specified, ignores `-d / --eth-privkey` and prompts the user to input their Ethereum private key | | Signup gatekeeper proxy data | `-s` or `--sg-data` | A hex string to pass to the sign-up gatekeeper proxy contract which may use it to determine whether to allow the user to sign up. Default: an empty bytestring. | | Initial voice credit proxy data | `-v` or `--ivcp-data` | A hex string to pass to the initial voice credit proxy contract which may use it to determine how many voice credits to assign to the user. Default: an empty bytestring. | -| The user's MACI private key | `-sk` or `--pubkey` | This should not be an Ethereum private key | -| Prompt for the user's MACI private key | `-dsk` or `--prompt-for-maci-privkey` | If specified, ignores `-sk / --privkey` and prompts the user to input thier MACI private key | -| State index | `-pi` or `--state-index` | The state index of the user | -| The user's new or current MACI public key | `-pp` or `--pubkey` | This should be a serialised BabyJub public key which should replace the user\'s public key in the state tree if the command is valid| -| Vote option index | `-pv` or `--vote-option-index` | The index of the option to vote for | -| New vote weight | `-pw` or `--new-vote-weight` | The vote weight to assign to said vote option | -| Nonce | `-pn` or `--nonce` | The nonce of the message | -| Salt | `-ps` or `--salt` | The salt of the message. If unspecified, this command will randomly generate a salt | ### User: Change key / vote @@ -149,10 +141,10 @@ Fields that the user has to set: |-|-|-| | Ethereum provider | `-e` or `--eth-provider` | A connection string to the Ethereum provider. Default: `http://localhost:8545` | | MACI contract address | `-x` or `--contract` | The address of the deployed MACI contract | -| User's Ethereum private key | `-d` or `--eth-privkey` | A private key of the Ethereum account to use to perform the transaction | -| Prompt for the user's Ethereum private key | `-dp` or `--prompt-for-eth-privkey` | If specified, ignores `-d / --eth-privkey` and prompts the user to input their Ethereum private key | | The user's MACI private key | `-sk` or `--pubkey` | This should not be an Ethereum private key | | Prompt for the user's MACI private key | `-dsk` or `--prompt-for-maci-privkey` | If specified, ignores `-sk / --privkey` and prompts the user to input thier MACI private key | +| User's Ethereum private key | `-d` or `--eth-privkey` | A private key of the Ethereum account to use to perform the transaction | +| Prompt for the user's Ethereum private key | `-dp` or `--prompt-for-eth-privkey` | If specified, ignores `-d / --eth-privkey` and prompts the user to input their Ethereum private key | | State index | `-i` or `--state-index` | The state index of the user | | The user's new or current MACI public key | `-p` or `--pubkey` | This should be a serialised BabyJub public key which should replace the user\'s public key in the state tree if the command is valid| | Vote option index | `-v` or `--vote-option-index` | The index of the option to vote for | diff --git a/cli/ts/publish.ts b/cli/ts/publish.ts index c803b38e56..abb977c16b 100644 --- a/cli/ts/publish.ts +++ b/cli/ts/publish.ts @@ -29,6 +29,8 @@ import { DEFAULT_ETH_PROVIDER, } from './defaults' +const DEFAULT_SALT = genRandomSalt() + const configureSubparser = (subparsers: any) => { const parser = subparsers.addParser( 'publish', @@ -44,6 +46,15 @@ const configureSubparser = (subparsers: any) => { } ) + parser.addArgument( + ['-p', '--pubkey'], + { + required: true, + type: 'string', + help: 'The MACI public key which should replace the user\'s public key in the state tree', + } + ) + parser.addArgument( ['-x', '--contract'], { @@ -91,15 +102,6 @@ const configureSubparser = (subparsers: any) => { } ) - parser.addArgument( - ['-p', '--pubkey'], - { - required: true, - type: 'string', - help: 'The MACI public key which should replace the user\'s public key in the state tree', - } - ) - parser.addArgument( ['-i', '--state-index'], { @@ -204,28 +206,46 @@ const publish = async (args: any) => { const userMaciPrivkey = PrivKey.unserialize(serializedPrivkey) - let stateIndex, voteOptionIndex, nonce, salt - try { - const results = validateArgs( - args.state_index, - args.vote_option_index, - args.nonce, - args.salt, - ) + // State index + const stateIndex = BigInt(args.state_index) + if (stateIndex < 0) { + console.error('Error: the state index must be greater than 0') + return + } - stateIndex = results.stateIndex - voteOptionIndex = results.voteOptionIndex - nonce = results.nonce - salt = results.salt + // Vote option index + const voteOptionIndex = BigInt(args.vote_option_index) - } catch (e) { - console.error(e.message) + if (voteOptionIndex < 0) { + console.error('Error: the vote option index should be 0 or greater') return } - // The new vote weight - // TODO: validate this - const newVoteWeight = BigInt(args.new_vote_weight) + // The nonce + const nonce = BigInt(args.nonce) + + if (nonce < 0) { + console.error('Error: the nonce should be 0 or greater') + return + } + + // The salt + let salt + if (args.salt) { + if (!validateSaltFormat(args.salt)) { + console.error('Error: the salt should be a 32-byte hexadecimal string') + return + } + + salt = BigInt(args.salt) + + if (!validateSaltSize(args.salt)) { + console.error('Error: the salt should less than the BabyJub field size') + return + } + } else { + salt = DEFAULT_SALT + } if (! (await checkDeployerProviderConnection(ethSk, ethProvider))) { console.error('Error: unable to connect to the Ethereum provider at', ethProvider) @@ -246,6 +266,13 @@ const publish = async (args: any) => { wallet, ) + // Validate the state index against the number of signups on-chain + const numSignUps = (await maciContract.numSignUps()).toNumber() + if (numSignUps < stateIndex) { + console.error('Error: the state index is invalid') + return + } + // Validate the vote option index against the max leaf index on-chain const maxVoteOptions = (await maciContract.voteOptionsMaxLeafIndex()).toNumber() if (maxVoteOptions < voteOptionIndex) { @@ -253,6 +280,9 @@ const publish = async (args: any) => { return } + // The new vote weight + const newVoteWeight = BigInt(args.new_vote_weight) + const coordinatorPubKeyOnChain = await maciContract.coordinatorPubKey() const coordinatorPubKey = new PubKey([ BigInt(coordinatorPubKeyOnChain.x.toString()), @@ -298,51 +328,7 @@ const publish = async (args: any) => { await tx.wait() } -const validateArgs = ( - stateIndex: BigInt, - voteOptionIndex: BigInt, - nonce: BigInt, - saltStr: string, -) => { - - // State index - if (stateIndex < BigInt(0)) { - throw new Error('Error: the state index must be greater than 0') - } - - // Vote option index - - if (voteOptionIndex < BigInt(0)) { - throw new Error('Error: the vote option index should be 0 or greater') - } - - // The nonce - if (nonce < BigInt(0)) { - throw new Error('Error: the nonce should be 0 or greater') - } - - // The salt - let salt - if (saltStr) { - if (!validateSaltFormat(saltStr)) { - throw new Error('Error: the salt should be a 32-byte hexadecimal string') - } - - if (!validateSaltSize(saltStr)) { - throw new Error('Error: the salt should less than the BabyJub field size') - } - - salt = BigInt(saltStr) - } else { - salt = genRandomSalt() - } - - return { stateIndex, voteOptionIndex, nonce, salt } - -} - export { publish, - validateArgs, configureSubparser, } diff --git a/cli/ts/signUp.ts b/cli/ts/signUp.ts index 1041362060..1e6218d5db 100644 --- a/cli/ts/signUp.ts +++ b/cli/ts/signUp.ts @@ -5,12 +5,8 @@ import { import { PubKey, - PrivKey, - Keypair, - Command, } from 'maci-domainobjs' -import { validateArgs } from './publish' import { promptPwd, @@ -61,25 +57,6 @@ const configureSubparser = (subparsers: any) => { } ) - const maciPrivkeyGroup = parser.addMutuallyExclusiveGroup({ required: true }) - - maciPrivkeyGroup.addArgument( - ['-dsk', '--prompt-for-maci-privkey'], - { - action: 'storeTrue', - help: 'Whether to prompt for your serialized MACI private key', - } - ) - - maciPrivkeyGroup.addArgument( - ['-sk', '--privkey'], - { - action: 'store', - type: 'string', - help: 'Your serialized MACI private key', - } - ) - const privkeyGroup = parser.addMutuallyExclusiveGroup({ required: true }) privkeyGroup.addArgument( @@ -116,65 +93,6 @@ const configureSubparser = (subparsers: any) => { help: 'A hex string to pass to the initial voice credit proxy contract which may use it to determine how many voice credits to assign to the user. Default: an empty bytestring.', } ) - - // For the command - parser.addArgument( - ['-pp', '--pubkey-to-publish'], - { - required: true, - type: 'string', - help: 'The MACI public key which should replace the user\'s public key in the state tree', - } - ) - - parser.addArgument( - ['-pi', '--state-index'], - { - required: true, - action: 'store', - type: 'int', - help: 'The user\'s state index', - } - ) - - parser.addArgument( - ['-pv', '--vote-option-index'], - { - required: true, - action: 'store', - type: 'int', - help: 'The vote option index', - } - ) - - parser.addArgument( - ['-pw', '--new-vote-weight'], - { - required: true, - action: 'store', - type: 'int', - help: 'The new vote weight', - } - ) - - parser.addArgument( - ['-pn', '--nonce'], - { - required: true, - action: 'store', - type: 'int', - help: 'The message nonce', - } - ) - - parser.addArgument( - ['-ps', '--salt'], - { - action: 'store', - type: 'string', - help: 'The message salt', - } - ) } const signup = async (args: any) => { @@ -251,73 +169,12 @@ const signup = async (args: any) => { wallet, ) - // The user's MACI private key - let serializedPrivkey - if (args.prompt_for_maci_privkey) { - serializedPrivkey = await promptPwd('Your MACI private key') - } else { - serializedPrivkey = args.privkey - } - - if (!PrivKey.isValidSerializedPrivKey(serializedPrivkey)) { - console.error('Error: invalid MACI private key') - return - } - - const userMaciPrivkey = PrivKey.unserialize(serializedPrivkey) - // Parse message options - const newVoteWeight = BigInt(args.new_vote_weight) - let stateIndex, voteOptionIndex, nonce, salt - try { - const results = validateArgs( - args.state_index, - args.vote_option_index, - args.nonce, - args.salt, - ) - - stateIndex = results.stateIndex - voteOptionIndex = results.voteOptionIndex - nonce = results.nonce - salt = results.salt - - } catch (e) { - console.error(e.message) - return - } - - const encKeypair = new Keypair() - const coordinatorPubKeyOnChain = await maciContract.coordinatorPubKey() - const coordinatorPubKey = new PubKey([ - BigInt(coordinatorPubKeyOnChain.x.toString()), - BigInt(coordinatorPubKeyOnChain.y.toString()), - ]) - - const command = new Command( - stateIndex, - userMaciPubKey, - voteOptionIndex, - newVoteWeight, - nonce, - salt, - ) - const signature = command.sign(userMaciPrivkey) - const message = command.encrypt( - signature, - Keypair.genEcdhSharedKey( - encKeypair.privKey, - coordinatorPubKey, - ) - ) - let tx try { tx = await maciContract.signUp( userMaciPubKey.asContractParam(), sgData, ivcpData, - message.asContractParam(), - encKeypair.pubKey.asContractParam(), { gasLimit: 1000000 } )