diff --git a/common-files/utils/web3.mjs b/common-files/utils/web3.mjs index 71fc430e3..faa9c3dc9 100644 --- a/common-files/utils/web3.mjs +++ b/common-files/utils/web3.mjs @@ -4,8 +4,6 @@ import Web3 from 'web3'; import config from 'config'; import logger from './logger.mjs'; -const { INFURA_PROJECT_SECRET } = process.env; - export default { connection() { if (!this.web3) this.connect(); @@ -20,22 +18,10 @@ export default { logger.info('Blockchain Connecting ...'); - let provider; - if (config.USE_INFURA) { - if (!INFURA_PROJECT_SECRET) throw Error('env INFURA_PROJECT_SECRET not set'); - - provider = new Web3.providers.WebsocketProvider(config.BLOCKCHAIN_URL, { - ...config.WEB3_PROVIDER_OPTIONS, - headers: { - authorization: `Basic ${Buffer.from(`:${INFURA_PROJECT_SECRET}`).toString('base64')}`, - }, - }); - } else { - provider = new Web3.providers.WebsocketProvider( - config.BLOCKCHAIN_URL, - config.WEB3_PROVIDER_OPTIONS, - ); - } + const provider = new Web3.providers.WebsocketProvider( + config.BLOCKCHAIN_URL, + config.WEB3_PROVIDER_OPTIONS, + ); provider.on('error', err => logger.error(`web3 error: ${err}`)); provider.on('connect', () => logger.info('Blockchain Connected ...')); diff --git a/config/default.js b/config/default.js index a33ea81f2..a6506ba7a 100644 --- a/config/default.js +++ b/config/default.js @@ -1,3 +1,4 @@ +/* eslint-disable no-nested-ternary */ const { DOMAIN_NAME = '' } = process.env; module.exports = { @@ -32,7 +33,6 @@ module.exports = { BLOCKCHAIN_URL: process.env.BLOCKCHAIN_URL || `ws://${process.env.BLOCKCHAIN_WS_HOST}:${process.env.BLOCKCHAIN_PORT}`, - USE_INFURA: process.env.USE_INFURA === 'true', ETH_PRIVATE_KEY: process.env.ETH_PRIVATE_KEY, // owner's/deployer's private key ETH_ADDRESS: process.env.ETH_ADDRESS, OPTIMIST_HOST: process.env.OPTIMIST_HOST || 'optimist', @@ -41,43 +41,6 @@ module.exports = { // Define Urls and Url format (http/ws vs https/wss, with vs without port) depending on whether a DOMAIN_NAME has been defined. // In production and staging environements, we require https/wss and no port, as traffic will be routed to the correct service // given a URL. - optimistBaseUrl: - DOMAIN_NAME === '' - ? `http://${process.env.OPTIMIST_HOST}:${process.env.OPTIMIST_HTTP_PORT}` - : `https://${process.env.OPTIMIST_HTTP_HOST}`, - optimistWsUrl: - DOMAIN_NAME === '' - ? `ws://${process.env.OPTIMIST_HOST}:${process.env.OPTIMIST_WS_PORT}` - : `wss://${process.env.OPTIMIST_HOST}`, - web3WsUrl: - DOMAIN_NAME === '' - ? `ws://${process.env.BLOCKCHAIN_WS_HOST}:${process.env.BLOCKCHAIN_PORT}` - : `wss://${process.env.BLOCKCHAIN_WS_HOST}`, - userEthereumSigningKey: - process.env.USER_ETHEREUM_SIGNING_KEY || - '0x4775af73d6dc84a0ae76f8726bda4b9ecf187c377229cb39e1afa7a18236a69e', // if changed, change associated userEthereumAddresses - userAddress: process.env.USER_ADDRESS, - UserEthereumAddresses: process.env.USER_ETHEREUM_ADDRESSES - ? process.env.USER_ETHEREUM_ADDRESSES.split(',') - : [ - '0x9c8b2276d490141ae1440da660e470e7c0349c63', - // '0x4ca4902a6f456b488947074ad4140317c7e21996', // 0xb0fa8745bd6e77a67ec6a27e701971d659937140cc3159d9f85210da3444eb45 - // '0xfCb059A4dB5B961d3e48706fAC91a55Bad0035C9', // 0xd42905d0582c476c4b74757be6576ec323d715a0c7dcff231b6348b7ab0190eb - ], - zkpMnemonic: - process.env.ZKP_MNEMONIC || - 'hurt labor ketchup seven scan swap dirt brown brush path goat together', - proposerEthereumSigningKey: - process.env.PROPOSER_ETHEREUM_SIGNING_KEY || - '0x4775af73d6dc84a0ae76f8726bda4b9ecf187c377229cb39e1afa7a18236a69d', - user1Pkd: process.env.RECIPIENT_PKD || [ - '0x193a37cd7973373aceae05d133f3d69ab6e7ef2f4321461173871ec7611244e2', - '0x27234a8721e73c9aa160154ee63d2470101fc5fd841221eeb675a91ec2d66e78', - ], - user2Pkd: process.env.RECIPIENT_PKD || [ - '0x105651c0c5bb97582b3270e0f5a07ca81410ffd1920e86697efddaec03dccef8', - '0x1ac3b61ecba1448e697b23d37efe290fb86554b2f905aaca3a6df59805eca366', - ], WEB3_OPTIONS: { gas: process.env.GAS || 8000000, gasPrice: process.env.GAS_PRICE || '20000000000', @@ -170,12 +133,28 @@ module.exports = { localhost: { name: 'Localhost', chainId: 4378921, - clientApiUrl: 'http://localhost:8080', - optimistApiUrl: 'http://localhost:8081', - optimistWsUrl: 'ws://localhost:8082', + clientApiUrl: process.env.CLIENT_HOST + ? DOMAIN_NAME === '' + ? `http://${process.env.CLIENT_HOST}:${process.env.CLIENT_PORT}` + : `https://${process.env.CLIENT_HOST}` + : 'http://localhost:8080', + optimistApiUrl: process.env.OPTIMIST_HOST + ? DOMAIN_NAME === '' + ? `http://${process.env.OPTIMIST_HOST}:${process.env.OPTIMIST_PORT}` + : `https://${process.env.OPTIMIST_HOST}` + : 'http://localhost:8081', + optimistWsUrl: process.env.OPTIMIST_HOST + ? DOMAIN_NAME === '' + ? `ws://${process.env.OPTIMIST_HOST}:${process.env.OPTIMIST_WS_PORT}` + : `wss://${process.env.OPTIMIST_HOST}` + : 'ws://localhost:8082', adversarialOptimistApiUrl: 'http://localhost:8088', adversarialOptimistWsUrl: 'ws://localhost:8089', - web3WsUrl: 'ws://localhost:8546', + web3WsUrl: process.env.BLOCKCHAIN_WS_HOST + ? DOMAIN_NAME === '' + ? `ws://${process.env.BLOCKCHAIN_WS_HOST}:${process.env.BLOCKCHAIN_PORT}` + : `wss://${process.env.BLOCKCHAIN_WS_HOST}` + : 'ws://localhost:8546', }, }, TEST_OPTIONS: { @@ -189,11 +168,11 @@ module.exports = { // this is the etherum private key for accounts[0] privateKey: '0x4775af73d6dc84a0ae76f8726bda4b9ecf187c377229cb39e1afa7a18236a69e', gas: 10000000, - gasCosts: 15000000000000000, + gasCosts: 80000000000000000, fee: 1, BLOCK_STAKE: 1, // 1 wei bond: 10, // 10 wei - txPerBlock: 2, + txPerBlock: process.env.TRANSACTIONS_PER_BLOCK || 2, signingKeys: { walletTest: '0xd42905d0582c476c4b74757be6576ec323d715a0c7dcff231b6348b7ab0190eb', user1: '0x4775af73d6dc84a0ae76f8726bda4b9ecf187c377229cb39e1afa7a18236a69e', @@ -204,6 +183,19 @@ module.exports = { challenger: '0xd42905d0582c476c4b74757be6576ec323d715a0c7dcff231b6348b7ab0190eb', liquidityProvider: '0xfbc1ee1c7332e2e5a76a99956f50b3ba2639aff73d56477e877ef8390c41e0c6', }, + addresses: { + walletTest: '0xfCb059A4dB5B961d3e48706fAC91a55Bad0035C9', + user1: '0x9C8B2276D490141Ae1440Da660E470E7C0349C63', + user2: '0xfCb059A4dB5B961d3e48706fAC91a55Bad0035C9', + proposer1: '0xfeEDA3882Dd44aeb394caEEf941386E7ed88e0E0', + proposer2: '0xfCb059A4dB5B961d3e48706fAC91a55Bad0035C9', + proposer3: '0x4789FD18D5d71982045d85d5218493fD69F55AC4', + challenger: '0xfCb059A4dB5B961d3e48706fAC91a55Bad0035C9', + liquidityProvider: '0x4789FD18D5d71982045d85d5218493fD69F55AC4', + }, + pkds: { + user1: '0x1ac3b61ecba1448e697b23d37efe290fb86554b2f905aaca3a6df59805eca366', + }, mnemonics: { user1: 'trip differ bamboo bundle bonus luxury strike mad merry muffin nose auction', user2: 'control series album tribe category saddle prosper enforce moon eternal talk fame', @@ -215,13 +207,23 @@ module.exports = { erc20default: 2000, }, }, - RESTRICTIONS: [ - { - name: 'MockERC20', - address: '0xB5Acbe9a0F1F8B98F3fC04471F7fE5d2c222cB44', - amount: 200, + RESTRICTIONS: { + signingKeys: { + bootProposerKey: '0x4775af73d6dc84a0ae76f8726bda4b9ecf187c377229cb39e1afa7a18236a69d', + bootChallengerKey: '0xd42905d0582c476c4b74757be6576ec323d715a0c7dcff231b6348b7ab0190eb', }, - ], + addresses: { + bootProposer: '0xfeEDA3882Dd44aeb394caEEf941386E7ed88e0E0', + bootChallenger: '0xfCb059A4dB5B961d3e48706fAC91a55Bad0035C9', + }, + tokens: [ + { + name: 'MockERC20', + address: '0xB5Acbe9a0F1F8B98F3fC04471F7fE5d2c222cB44', + amount: 200, + }, + ], + }, // for Browser use proposerUrl: diff --git a/docker-compose.ganache.yml b/docker-compose.ganache.yml index 440b6ba78..ab294fce6 100644 --- a/docker-compose.ganache.yml +++ b/docker-compose.ganache.yml @@ -7,7 +7,7 @@ services: image: trufflesuite/ganache-cli:v6.12.1 ports: - 8546:8546 - command: + command: ganache-cli --accounts=10 --defaultBalanceEther=1000 --gasLimit=0x3B9ACA00 --deterministic -i 4378921 -p 8546 -b 1 --account="0x4775af73d6dc84a0ae76f8726bda4b9ecf187c377229cb39e1afa7a18236a69e,10000000000000000000000" --account="0x4775af73d6dc84a0ae76f8726bda4b9ecf187c377229cb39e1afa7a18236a69d,10000000000000000000000" diff --git a/docker-compose.infura.yml b/docker-compose.infura.yml deleted file mode 100644 index c973a444d..000000000 --- a/docker-compose.infura.yml +++ /dev/null @@ -1,43 +0,0 @@ -version: '3.5' -# Use this script for running up nightfall_3 in 'ropsten' mode with local -# Use it as an override file for docker-compose.yml -# See the readme for more information. -services: - client1: - environment: - BLOCKCHAIN_URL: 'wss://ropsten.infura.io/ws/v3/${INFURA_PROJECT_ID}' - USE_INFURA: 'true' - AUTOSTART_RETRIES: 500 - INFURA_PROJECT_SECRET: $INFURA_PROJECT_SECRET - - client2: - environment: - BLOCKCHAIN_URL: 'wss://ropsten.infura.io/ws/v3/${INFURA_PROJECT_ID}' - USE_INFURA: 'true' - AUTOSTART_RETRIES: 500 - INFURA_PROJECT_SECRET: $INFURA_PROJECT_SECRET - - deployer: - environment: - # ETH_NETWORK sets the network selected by Truffle from truffle-config.js - # startup routines will wait for a blockchain client to be reachable on this network - ETH_NETWORK: ropsten - BLOCKCHAIN_URL: 'wss://:${INFURA_PROJECT_SECRET}@ropsten.infura.io/ws/v3/${INFURA_PROJECT_ID}' - USE_INFURA: 'true' - FROM_ADDRESS: '0x29100E7E3dA6654BF63d9E7804ADe518aCc5AaA5' - ETH_PRIVATE_KEY: $ETH_PRIVATE_KEY - INFURA_PROJECT_SECRET: $INFURA_PROJECT_SECRET - - optimist1: - environment: - BLOCKCHAIN_URL: 'wss://ropsten.infura.io/ws/v3/${INFURA_PROJECT_ID}' - USE_INFURA: 'true' - AUTOSTART_RETRIES: 500 - INFURA_PROJECT_SECRET: $INFURA_PROJECT_SECRET - - optimist2: - environment: - BLOCKCHAIN_URL: 'wss://ropsten.infura.io/ws/v3/${INFURA_PROJECT_ID}' - USE_INFURA: 'true' - AUTOSTART_RETRIES: 500 - INFURA_PROJECT_SECRET: $INFURA_PROJECT_SECRET diff --git a/nightfall-client/docker-entrypoint.sh b/nightfall-client/docker-entrypoint.sh index 7d3fb7853..987efc76d 100755 --- a/nightfall-client/docker-entrypoint.sh +++ b/nightfall-client/docker-entrypoint.sh @@ -3,7 +3,7 @@ mongod --dbpath /app/mongodb/ --fork --logpath /var/log/mongodb/mongod.log --bin while ! nc -z localhost 27017; do sleep 3; done echo 'mongodb started' -if [ -z "${USE_INFURA}" ] && [ -z "${USE_ROPSTEN_NODE}" ]; +if [ -z "${USE_ROPSTEN_NODE}" ]; then # wait until there's a blockchain client up while ! nc -z ${BLOCKCHAIN_WS_HOST} ${BLOCKCHAIN_PORT}; do sleep 3; done diff --git a/nightfall-deployer/contracts/Challenges.sol b/nightfall-deployer/contracts/Challenges.sol index 8eb1a3056..3642f161f 100644 --- a/nightfall-deployer/contracts/Challenges.sol +++ b/nightfall-deployer/contracts/Challenges.sol @@ -38,7 +38,7 @@ contract Challenges is Stateful, Key_Registry, Config { uint256 blockNumberL2, Transaction[] memory transactions, bytes32 salt - ) external { + ) external onlyBootChallenger { checkCommit(msg.data); // check if the block hash is correct and the block hash exists for the block and prior block state.isBlockReal(priorBlockL2, priorBlockTransactions, blockNumberL2 - 1); @@ -73,7 +73,7 @@ contract Challenges is Stateful, Key_Registry, Config { uint256 blockNumberL2, Transaction[] memory transactions, bytes32 salt - ) external { + ) external onlyBootChallenger { checkCommit(msg.data); // check if the block hash is correct and the block hash exists for the block and prior block state.isBlockReal(priorBlockL2, priorBlockTransactions, blockNumberL2 - 1); @@ -104,7 +104,7 @@ contract Challenges is Stateful, Key_Registry, Config { uint256 transactionIndex1, uint256 transactionIndex2, bytes32 salt - ) external { + ) external onlyBootChallenger { checkCommit(msg.data); // first, check we have real, in-train, contiguous blocks state.isBlockReal(block1, transactions1, block1NumberL2); @@ -132,7 +132,7 @@ contract Challenges is Stateful, Key_Registry, Config { Transaction[] memory transactions, uint256 transactionIndex, bytes32 salt - ) external { + ) external onlyBootChallenger { checkCommit(msg.data); state.isBlockReal(blockL2, transactions, blockNumberL2); ChallengesUtil.libChallengeTransactionType(transactions[transactionIndex]); @@ -148,7 +148,7 @@ contract Challenges is Stateful, Key_Registry, Config { uint256 transactionIndex, uint256[8] memory uncompressedProof, bytes32 salt - ) external { + ) external onlyBootChallenger { checkCommit(msg.data); state.isBlockReal(blockL2, transactions, blockNumberL2); // now we need to check that the proof is correct @@ -176,7 +176,7 @@ contract Challenges is Stateful, Key_Registry, Config { Transaction[] memory transactionsOfblockL2ContainingHistoricRoot, uint256[8] memory uncompressedProof, bytes32 salt - ) external { + ) external onlyBootChallenger { checkCommit(msg.data); state.isBlockReal(blockL2, transactions, blockNumberL2); state.isBlockReal( @@ -215,7 +215,7 @@ contract Challenges is Stateful, Key_Registry, Config { Transaction[] memory transactionsOfblockL2ContainingHistoricRoot2, uint256[8] memory uncompressedProof, bytes32 salt - ) external { + ) external onlyBootChallenger { checkCommit(msg.data); state.isBlockReal(blockL2, transactions, blockNumberL2); state.isBlockReal( @@ -266,7 +266,7 @@ contract Challenges is Stateful, Key_Registry, Config { uint256 transactionIndex2, uint256 nullifierIndex2, bytes32 salt - ) public { + ) public onlyBootChallenger { checkCommit(msg.data); ChallengesUtil.libChallengeNullifier( txs1[transactionIndex1], @@ -297,7 +297,7 @@ contract Challenges is Stateful, Key_Registry, Config { Transaction[] memory transactions, uint256 transactionIndex, bytes32 salt - ) external { + ) external onlyBootChallenger { checkCommit(msg.data); state.isBlockReal(blockL2, transactions, blockNumberL2); if ( @@ -367,7 +367,7 @@ contract Challenges is Stateful, Key_Registry, Config { } //To prevent frontrunning, we need to commit to a challenge before we send it - function commitToChallenge(bytes32 commitHash) external { + function commitToChallenge(bytes32 commitHash) external onlyBootChallenger { require(committers[commitHash] == address(0), 'Hash is already committed to'); committers[commitHash] = msg.sender; emit CommittedToChallenge(commitHash, msg.sender); diff --git a/nightfall-deployer/contracts/Config.sol b/nightfall-deployer/contracts/Config.sol index 8c0ca38a6..82d8c3835 100644 --- a/nightfall-deployer/contracts/Config.sol +++ b/nightfall-deployer/contracts/Config.sol @@ -11,12 +11,43 @@ contract Config is Ownable { uint256 constant COOLING_OFF_PERIOD = 1 weeks; bytes32 constant ZERO = bytes32(0); + address bootProposer; + address bootChallenger; mapping(address => uint256) erc20limit; function initialize() public virtual override initializer { Ownable.initialize(); } + // restricting proposers + modifier onlyBootProposer() { + require(msg.sender == bootProposer, 'You are not the boot proposer'); + _; + } + + function setBootProposer(address proposer) external onlyOwner { + bootProposer = proposer; + } + + function getBootProposer() external view returns (address) { + return bootProposer; + } + + // restricting challengers + modifier onlyBootChallenger() { + require(msg.sender == bootChallenger, 'You are not the boot challenger'); + _; + } + + function setBootChallenger(address challenger) external onlyOwner { + bootChallenger = challenger; + } + + function getBootChallenger() external view returns (address) { + return bootChallenger; + } + + // restricting tokens function getRestriction(address tokenAddr) public view returns (uint256) { return erc20limit[tokenAddr]; } diff --git a/nightfall-deployer/contracts/Proposers.sol b/nightfall-deployer/contracts/Proposers.sol index 85c0e3d0b..b05c4aba2 100644 --- a/nightfall-deployer/contracts/Proposers.sol +++ b/nightfall-deployer/contracts/Proposers.sol @@ -35,7 +35,7 @@ contract Proposers is Stateful, Structures, Config, ReentrancyGuardUpgradeable { } //add the proposer to the circular linked list - function registerProposer(string memory url) external payable nonReentrant { + function registerProposer(string memory url) external payable nonReentrant onlyBootProposer { require(REGISTRATION_BOND <= msg.value, 'The registration payment is incorrect'); require( state.getProposer(msg.sender).thisAddress == address(0), @@ -113,10 +113,10 @@ contract Proposers is Stateful, Structures, Config, ReentrancyGuardUpgradeable { // Proposers can change REST API URL function updateProposer(string memory url) external { - require( - state.getProposer(msg.sender).thisAddress != address(0), - 'This proposer is not registered or you are not that proposer' - ); - state.updateProposer(msg.sender, url); + require( + state.getProposer(msg.sender).thisAddress != address(0), + 'This proposer is not registered or you are not that proposer' + ); + state.updateProposer(msg.sender, url); } } diff --git a/nightfall-deployer/entrypoint.sh b/nightfall-deployer/entrypoint.sh index f7e1cbf10..b85313159 100755 --- a/nightfall-deployer/entrypoint.sh +++ b/nightfall-deployer/entrypoint.sh @@ -2,7 +2,7 @@ set -o errexit set -o pipefail -if [ -z "${USE_INFURA}" ] && [ -z "${ETH_PRIVATE_KEY}" ]; then +if [ -z "${ETH_PRIVATE_KEY}" ]; then # wait until there's a blockchain client up while ! nc -z ${BLOCKCHAIN_WS_HOST} ${BLOCKCHAIN_PORT}; do sleep 3; done fi diff --git a/nightfall-deployer/migrations/2_deploy_upgradeable.js b/nightfall-deployer/migrations/2_deploy_upgradeable.js index d6edc333c..0a58ee7df 100644 --- a/nightfall-deployer/migrations/2_deploy_upgradeable.js +++ b/nightfall-deployer/migrations/2_deploy_upgradeable.js @@ -12,6 +12,10 @@ const Proposers = artifacts.require('Proposers.sol'); const Challenges = artifacts.require('Challenges.sol'); const State = artifacts.require('State.sol'); +const config = require('config'); + +const { addresses } = config.RESTRICTIONS; + module.exports = async function (deployer) { await deployer.deploy(Verifier); await deployer.link(Verifier, [Challenges, ChallengesUtil]); @@ -33,4 +37,10 @@ module.exports = async function (deployer) { deployer, unsafeAllowLinkedLibraries: true, }); + + const proposers = await Proposers.deployed(); + const challengers = await Challenges.deployed(); + const { bootProposer, bootChallenger } = addresses; + await proposers.setBootProposer(bootProposer); + await challengers.setBootChallenger(bootChallenger); }; diff --git a/nightfall-deployer/migrations/3_test_tokens_migration.js b/nightfall-deployer/migrations/3_test_tokens_migration.js index 8d43753cc..1bbb5f044 100644 --- a/nightfall-deployer/migrations/3_test_tokens_migration.js +++ b/nightfall-deployer/migrations/3_test_tokens_migration.js @@ -1,9 +1,9 @@ const config = require('config'); const { - UserEthereumAddresses, TEST_OPTIONS: { restrictions: { erc20default }, + addresses, }, } = config; @@ -24,9 +24,9 @@ module.exports = function (deployer, _, accounts) { const ERC20deployed = await ERC20Mock.deployed(); // For ping pong tests - for (const address of UserEthereumAddresses) { - await ERC20deployed.transfer(address, 1000000000000); - } + await ERC20deployed.transfer(addresses.user1, 1000000000000); + await ERC20deployed.transfer(addresses.user2, 1000000000000); + // Set a restriction for ping-pong await restrictions.setRestriction(ERC20deployed.address, erc20default); @@ -39,22 +39,18 @@ module.exports = function (deployer, _, accounts) { const ERC1155deployed = await ERC1155Mock.deployed(); // For e2e tests for (let i = 0; i < nERC721; i++) { - for (const address of UserEthereumAddresses) { - await ERC721deployed.awardItem(address, `https://erc721mock/item-id-${i}.json`); - } + await ERC721deployed.awardItem(addresses.user1, `https://erc721mock/item-id-${i}.json`); } // For testing the wallet await ERC20deployed.transfer(liquidityProviderAddress, 1000000000000); - for (const address of UserEthereumAddresses) { - await ERC1155deployed.safeBatchTransferFrom( - accounts[0], - address, - [0, 1, 2, 3, 4], - [100000, 200000, 2, 50, 80000], - [], - ); - } + await ERC1155deployed.safeBatchTransferFrom( + accounts[0], + addresses.user1, + [0, 1, 2, 3, 4], + [100000, 200000, 2, 50, 80000], + [], + ); } }); }; diff --git a/nightfall-deployer/src/circuit-setup.mjs b/nightfall-deployer/src/circuit-setup.mjs index 8662ba5af..cf33a3366 100644 --- a/nightfall-deployer/src/circuit-setup.mjs +++ b/nightfall-deployer/src/circuit-setup.mjs @@ -134,7 +134,7 @@ async function setupCircuits() { // when deploying on infura - do serial tx execution to avoid nonce issue // when using a private key, we shouldn't assume an unlocked account and we sign the transaction directly - if (config.USE_INFURA || config.ETH_PRIVATE_KEY) { + if (config.ETH_PRIVATE_KEY) { await Web3.submitRawTransaction(await tx.encodeABI(), keyRegistryAddress); } else await tx.send(); } catch (err) { diff --git a/nightfall-deployer/src/contract-setup.mjs b/nightfall-deployer/src/contract-setup.mjs index 1a10bf5f0..dc1df3a6f 100644 --- a/nightfall-deployer/src/contract-setup.mjs +++ b/nightfall-deployer/src/contract-setup.mjs @@ -15,7 +15,7 @@ async function setupCircuits() { // when deploying on infura // do serial registration to predict nonce // or, if we have the owner's private key, sign with that, rather than use an unlocked account - if (config.USE_INFURA || config.ETH_PRIVATE_KEY) { + if (config.ETH_PRIVATE_KEY) { await Web3.submitRawTransaction( (await waitForContract('Proposers')).methods .setStateContract(stateInstance.options.address) diff --git a/nightfall-optimist/docker-entrypoint.sh b/nightfall-optimist/docker-entrypoint.sh index 1fe0da279..f8ef4d0e5 100755 --- a/nightfall-optimist/docker-entrypoint.sh +++ b/nightfall-optimist/docker-entrypoint.sh @@ -4,7 +4,7 @@ mongod --dbpath /app/mongodb/ --fork --logpath /var/log/mongodb/mongod.log --bin while ! nc -z localhost 27017; do sleep 3; done echo 'mongodb started' -if [ -z "${USE_INFURA}" ] && [ -z "${USE_ROPSTEN_NODE}" ]; +if [ -z "${USE_ROPSTEN_NODE}" ]; then # wait until there's a blockchain client up while ! nc -z ${BLOCKCHAIN_WS_HOST} ${BLOCKCHAIN_PORT}; do sleep 3; done diff --git a/package-lock.json b/package-lock.json index 2b71ef90f..7bf5f21c1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1785,54 +1785,6 @@ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.4.tgz", "integrity": "sha512-SA5mXJWrId1TaQjfxUYghbqQ/hYioKmLJvPJyDuYRtXXenFNMjj4hSSt1Cf1xsuXSXrtxrVC5Ot4eU6cOtBDdA==" }, - "aws-sdk": { - "version": "2.1084.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1084.0.tgz", - "integrity": "sha512-fhMjPRrrln8LhMZw17IyrzkVXCG6okFMrZzgIZN1h63WWGot65qcIvYfUn7YyHpYWMLBeND8MRfW6x6PIqJBdA==", - "dev": true, - "requires": { - "buffer": "4.9.2", - "events": "1.1.1", - "ieee754": "1.1.13", - "jmespath": "0.16.0", - "querystring": "0.2.0", - "sax": "1.2.1", - "url": "0.10.3", - "uuid": "3.3.2", - "xml2js": "0.4.19" - }, - "dependencies": { - "buffer": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", - "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", - "dev": true, - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" - } - }, - "events": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", - "dev": true - }, - "ieee754": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", - "dev": true - }, - "uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", - "dev": true - } - } - }, "aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", @@ -2485,7 +2437,6 @@ "version": "file:common-files", "dev": true, "requires": { - "aws-sdk": "^2.1084.0", "config": "^3.3.7", "winston": "^3.6.0" }, @@ -3452,6 +3403,23 @@ } } }, + "eslint-plugin-cypress": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-cypress/-/eslint-plugin-cypress-2.12.1.tgz", + "integrity": "sha512-c2W/uPADl5kospNDihgiLc7n87t5XhUbFDoTl6CfVkmG+kDAb5Ux10V9PoLPu9N+r7znpc+iQlcmAqT1A/89HA==", + "dev": true, + "requires": { + "globals": "^11.12.0" + }, + "dependencies": { + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + } + } + }, "eslint-plugin-import": { "version": "2.25.2", "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.25.2.tgz", @@ -5101,12 +5069,6 @@ "supports-color": "^7.0.0" } }, - "jmespath": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz", - "integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==", - "dev": true - }, "js-sha3": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", @@ -6633,12 +6595,6 @@ "strict-uri-encode": "^1.0.0" } }, - "querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", - "dev": true - }, "queue": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", @@ -6973,12 +6929,6 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, - "sax": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", - "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=", - "dev": true - }, "schema-utils": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", @@ -7959,24 +7909,6 @@ "punycode": "^2.1.0" } }, - "url": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", - "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", - "dev": true, - "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" - }, - "dependencies": { - "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", - "dev": true - } - } - }, "url-parse-lax": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", @@ -8673,22 +8605,6 @@ "cookiejar": "^2.1.1" } }, - "xml2js": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", - "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", - "dev": true, - "requires": { - "sax": ">=0.6.0", - "xmlbuilder": "~9.0.1" - } - }, - "xmlbuilder": { - "version": "9.0.7", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", - "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=", - "dev": true - }, "xmlcreate": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", diff --git a/package.json b/package.json index 54e456341..3a2e99139 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "scripts": { "neg-test": "mocha --timeout 0 --bail --exit test/neg-http.mjs", "neg-test-ropsten": "mocha --timeout 0 --bail --exit test/neg-http.mjs", - "test-e2e-protocol": "LOG_LEVEL=error mocha --timeout 0 --bail --parallel --exit test/e2e/protocol/*.test.mjs ", + "test-e2e-protocol": "LOG_LEVEL=debug mocha --timeout 0 --bail --exit test/e2e/protocol/*.test.mjs ", "test-gas": "mocha --timeout 0 --bail --exit test/e2e/gas.test.mjs ", "test-e2e-tokens": "LOG_LEVEL=error mocha --timeout 0 --bail --exit test/e2e/tokens/*.test.mjs ", "lint": "eslint . --ext js,mjs,jsx && find-unused-exports", @@ -41,6 +41,7 @@ "eslint": "^7.25.0", "eslint-config-codfish": "^10.0.0", "eslint-config-prettier": "^8.3.0", + "eslint-plugin-cypress": "^2.12.1", "eslint-plugin-import": "^2.25.2", "eslint-plugin-prettier": "^4.0.0", "eslint-plugin-react": "^7.26.1", diff --git a/start-nightfall b/start-nightfall index b18bef61e..6d44c709d 100755 --- a/start-nightfall +++ b/start-nightfall @@ -13,7 +13,6 @@ usage() echo " -s or --stubs; runs with circuits stubbed out (faster but no checking of ZKP code) - use with either -g or -l" echo " -h or --help; to print this message" echo " -d or --dev; to bind mount the filesystem and use it for development" - echo " -i or --infura; to connect infura ropsten testnet" echo " -r or --ropsten to connect testnet node (Note: please set environment variable ROPSTEN_NODE, FROM_ADDRESS, and ETH_PRIVATE_KEY. Find more description in README.md)" } @@ -43,8 +42,6 @@ while [ -n "$1" ]; do ;; -r | --ropsten ) FILE="-f docker-compose.yml -f docker-compose.ropsten.yml" ;; - -i | --infura ) FILE="-f docker-compose.yml -f docker-compose.infura.yml" - ;; -h | --help ) usage ;; -s | --stubs ) STUBS="-f docker-compose.stubs.yml" diff --git a/test/e2e/protocol/challenger.test.mjs b/test/e2e/protocol/challenger.test.mjs index 2a3f86cc3..14890b6f5 100644 --- a/test/e2e/protocol/challenger.test.mjs +++ b/test/e2e/protocol/challenger.test.mjs @@ -12,30 +12,29 @@ chai.use(chaiAsPromised); const environment = config.ENVIRONMENTS[process.env.ENVIRONMENT] || config.ENVIRONMENTS.localhost; -const { mnemonics, signingKeys } = config.TEST_OPTIONS; +const { signingKeys } = config.RESTRICTIONS; +const { mnemonics } = config.TEST_OPTIONS; -const nf3Challenger = new Nf3(signingKeys.challenger, environment); +const bootChallenger = new Nf3(signingKeys.bootChallengerKey, environment); describe('Basic Challenger tests', () => { before(async () => { - await nf3Challenger.init(mnemonics.challenger); - // Challenger registration - await nf3Challenger.registerChallenger(); - // Chalenger listening for incoming events - nf3Challenger.startChallenger(); + await bootChallenger.init(mnemonics.challenger); }); - it('should register a challenger', async () => { - const res = await nf3Challenger.registerChallenger(); - expect(res.status).to.be.equal(200); + it('should register the boot challenger', async () => { + // Challenger registration + await bootChallenger.registerChallenger(); + // Chalenger listening for incoming events + bootChallenger.startChallenger(); }); it('should de-register a challenger', async () => { - const res = await nf3Challenger.deregisterChallenger(); + const res = await bootChallenger.deregisterChallenger(); expect(res.status).to.be.equal(200); }); after(async () => { - await nf3Challenger.close(); + await bootChallenger.close(); }); }); diff --git a/test/e2e/protocol/proposer.test.mjs b/test/e2e/protocol/proposer.test.mjs index 28245b8c2..0706d24af 100644 --- a/test/e2e/protocol/proposer.test.mjs +++ b/test/e2e/protocol/proposer.test.mjs @@ -15,8 +15,6 @@ chai.use(chaiAsPromised); const environment = config.ENVIRONMENTS[process.env.ENVIRONMENT] || config.ENVIRONMENTS.localhost; const { - bond, - gasCosts, txPerBlock, mnemonics, signingKeys, @@ -25,11 +23,8 @@ const { fee, } = config.TEST_OPTIONS; -const testProposers = [ - new Nf3(signingKeys.proposer1, environment), - new Nf3(signingKeys.proposer2, environment), - new Nf3(signingKeys.proposer3, environment), -]; +const bootProposer = new Nf3(signingKeys.proposer1, environment); +const testProposer = new Nf3(signingKeys.proposer2, environment); const testProposersUrl = [ 'http://test-proposer1', @@ -71,17 +66,15 @@ describe('Basic Proposer tests', () => { tokenId, fee, ); - - for (const prop of testProposers) { - await prop.init(mnemonics.proposer); - } + await bootProposer.init(mnemonics.proposer); + await testProposer.init(mnemonics.proposer); // Proposer registration - await testProposers[0].registerProposer(testProposersUrl[0]); + await bootProposer.registerProposer(testProposersUrl[0]); let blocksReceivedToPropose = 0; // Proposer listening for incoming events - const newGasBlockEmitter = await testProposers[0].startProposer(); + const newGasBlockEmitter = await bootProposer.startProposer(); newGasBlockEmitter.on('gascost', async (gasUsed, blocksToPropose) => { blocksReceivedToPropose = blocksToPropose; logger.debug( @@ -99,55 +92,32 @@ describe('Basic Proposer tests', () => { expect(blocksReceivedToPropose).to.be.equal(Math.floor(totalDeposits / txPerBlock)); }); - it('should register a proposer', async () => { - let proposers; - ({ proposers } = await testProposers[1].getProposers()); - // we have to pay 10 ETH to be registered - const startBalance = await web3Client.getBalance(testProposers[1].ethereumAddress); - const res = await testProposers[1].registerProposer(testProposersUrl[1]); - expectTransaction(res); - ({ proposers } = await testProposers[1].getProposers()); - const endBalance = await web3Client.getBalance(testProposers[1].ethereumAddress); - expect(endBalance - startBalance).to.closeTo(-bond, gasCosts); - const thisProposer = proposers.filter(p => p.thisAddress === testProposers[1].ethereumAddress); - expect(thisProposer.length).to.be.equal(1); - expect(proposers[0].url).to.be.equal(testProposersUrl[0]); - expect(proposers[1].url).to.be.equal(testProposersUrl[1]); - }); - - it('should register other proposer', async () => { - let proposers; - ({ proposers } = await testProposers[2].getProposers()); - // we have to pay 10 ETH to be registered - const startBalance = await web3Client.getBalance(testProposers[2].ethereumAddress); - const res = await testProposers[2].registerProposer(testProposersUrl[2]); - expectTransaction(res); - ({ proposers } = await testProposers[2].getProposers()); - const endBalance = await web3Client.getBalance(testProposers[2].ethereumAddress); - expect(endBalance - startBalance).to.closeTo(-bond, gasCosts); - const thisProposer = proposers.filter(p => p.thisAddress === testProposers[2].ethereumAddress); - expect(thisProposer.length).to.be.equal(1); - expect(proposers[0].url).to.be.equal(testProposersUrl[0]); - expect(proposers[1].url).to.be.equal(testProposersUrl[1]); - expect(proposers[2].url).to.be.equal(testProposersUrl[2]); + it('should fail to register a proposer other than the boot proposer', async () => { + try { + const res = await testProposer.registerProposer(); + expectTransaction(res); + } catch (error) { + expect(error.message).to.satisfy(message => + message.includes('Transaction has been reverted by the EVM'), + ); + } }); it('should update proposers url', async () => { let proposers; - ({ proposers } = await testProposers[2].getProposers()); + ({ proposers } = await bootProposer.getProposers()); // we have to pay 10 ETH to be registered - const res = await testProposers[2].updateProposer(testProposersUrl[3]); + const res = await bootProposer.updateProposer(testProposersUrl[3]); expectTransaction(res); - ({ proposers } = await testProposers[2].getProposers()); - const thisProposer = proposers.filter(p => p.thisAddress === testProposers[2].ethereumAddress); + ({ proposers } = await bootProposer.getProposers()); + const thisProposer = proposers.filter(p => p.thisAddress === bootProposer.ethereumAddress); expect(thisProposer.length).to.be.equal(1); - expect(proposers[0].url).to.be.equal(testProposersUrl[0]); - expect(proposers[1].url).to.be.equal(testProposersUrl[1]); - expect(proposers[2].url).to.be.equal(testProposersUrl[3]); + expect(proposers[0].url).to.be.equal(testProposersUrl[3]); }); + it('should fail to register a proposer twice', async () => { try { - const res = await testProposers[2].registerProposer(testProposersUrl[2]); + const res = await bootProposer.registerProposer(testProposersUrl[2]); expectTransaction(res); expect.fail('Submitting the same proposer registration should have caused an EVM revert'); @@ -156,24 +126,22 @@ describe('Basic Proposer tests', () => { } }); - it('should unregister a proposer', async () => { + it('should unregister the boot proposer', async () => { let proposers; - ({ proposers } = await testProposers[0].getProposers()); - let thisProposer = proposers.filter(p => p.thisAddress === testProposers[0].ethereumAddress); + ({ proposers } = await bootProposer.getProposers()); + let thisProposer = proposers.filter(p => p.thisAddress === bootProposer.ethereumAddress); expect(thisProposer.length).to.be.equal(1); - const res = await testProposers[0].deregisterProposer(); + const res = await bootProposer.deregisterProposer(); expectTransaction(res); - ({ proposers } = await testProposers[0].getProposers()); - thisProposer = proposers.filter(p => p.thisAddress === testProposers[0].ethereumAddress); + ({ proposers } = await bootProposer.getProposers()); + thisProposer = proposers.filter(p => p.thisAddress === bootProposer.ethereumAddress); expect(thisProposer.length).to.be.equal(0); - expect(proposers[0].url).to.be.equal(testProposersUrl[1]); - expect(proposers[1].url).to.be.equal(testProposersUrl[3]); }); it('Should create a failing withdrawBond (because insufficient time has passed)', async () => { let error = null; try { - await testProposers[0].withdrawBond(); + await bootProposer.withdrawBond(); } catch (err) { error = err; } @@ -188,12 +156,12 @@ describe('Basic Proposer tests', () => { it('Should create a passing withdrawBond (because sufficient time has passed)', async () => { if ((await web3Client.getInfo()).includes('TestRPC')) await web3Client.timeJump(3600 * 24 * 10); // jump in time by 7 days if ((await web3Client.getInfo()).includes('TestRPC')) { - const res = await testProposers[0].withdrawBond(); + const res = await bootProposer.withdrawBond(); expectTransaction(res); } else { let error = null; try { - await testProposers[0].withdrawBond(); + await bootProposer.withdrawBond(); } catch (err) { error = err; } @@ -202,17 +170,9 @@ describe('Basic Proposer tests', () => { }); after(async () => { - // After the proposer tests, de-register proposers - let { proposers } = await testProposers[0].getProposers(); - - for (const prop of testProposers) { - if (Object.values(proposers[0]).includes(prop.ethereumAddress)) - await prop.deregisterProposer(); - prop.close(); - } - ({ proposers } = await testProposers[0].getProposers()); - - expect(proposers[0].url).to.be.equal(''); + // After the proposer tests, unregister proposers + await testProposer.close(); + await bootProposer.close(); web3Client.closeWeb3(); }); }); diff --git a/test/e2e/tokens/erc20.test.mjs b/test/e2e/tokens/erc20.test.mjs index eeeb1350d..10ea3baff 100644 --- a/test/e2e/tokens/erc20.test.mjs +++ b/test/e2e/tokens/erc20.test.mjs @@ -26,7 +26,9 @@ const { restrictions: { erc20default }, } = config.TEST_OPTIONS; -const { RESTRICTIONS: defaultRestrictions } = config; +const { + RESTRICTIONS: { tokens: defaultRestrictions }, +} = config; const nf3Users = [new Nf3(signingKeys.user1, environment), new Nf3(signingKeys.user2, environment)]; const nf3Proposer = new Nf3(signingKeys.proposer1, environment); diff --git a/test/neg-http.mjs b/test/neg-http.mjs index 8e1986c1c..2b6384f76 100644 --- a/test/neg-http.mjs +++ b/test/neg-http.mjs @@ -29,7 +29,6 @@ describe('Testing the challenge http API', () => { let pkd1; let compressedPkd1; - const USE_INFURA = process.env.USE_INFURA === 'true'; const USE_ROPSTEN_NODE = process.env.USE_ROPSTEN_NODE === 'true'; const { ETH_PRIVATE_KEY, BLOCKCHAIN_URL } = process.env; const web3WsUrl = BLOCKCHAIN_URL || process.env.web3WsUrl; @@ -83,7 +82,7 @@ describe('Testing the challenge http API', () => { before(async () => { web3 = await web3Client.getWeb3(web3WsUrl); - if (USE_INFURA || USE_ROPSTEN_NODE) { + if (USE_ROPSTEN_NODE) { if (!ETH_PRIVATE_KEY) { throw Error( 'Cannot use default private key, please set environment variable ETH_PRIVATE_KEY', diff --git a/test/ping-pong/docker-compose.host.docker.internal.yml b/test/ping-pong/docker-compose.host.docker.internal.yml index e43483f8e..1b0361333 100644 --- a/test/ping-pong/docker-compose.host.docker.internal.yml +++ b/test/ping-pong/docker-compose.host.docker.internal.yml @@ -22,8 +22,6 @@ services: ETH_PRIVATE_KEY: abf4ed9f30bd1e4a290310d726c7bbdf39cd75a25eebd9a3a4874e10b4a0c4ce ETH_ADDRESS: '0xdb080dC48961bC1D67a0A4151572eCb824cC76E8' GAS_PRICE: 20000000000 - # This is only needed for test purposes - it gives tokens to the user at startup - USER_ETHEREUM_ADDRESSES: 0xE35B7c8338E4B952C03E73B50f454B1df086fef2,0x4637Ee1126723e098A152f33F326fb767A6A2b8A optimist: extra_hosts: @@ -39,7 +37,6 @@ services: environment: BLOCKCHAIN_WS_HOST: host.docker.internal BLOCKCHAIN_PORT: 8546 - PROPOSER_ETHEREUM_SIGNING_KEY: 645ac79fa9fd87dd1cf30bdca51d326bd501cd328d6dbc9f5f517c7da0dafa6f user-local1: extra_hosts: @@ -55,7 +52,6 @@ services: RECIPIENT_PKD: '0x1ac3b61ecba1448e697b23d37efe290fb86554b2f905aaca3a6df59805eca366' ZKP_MNEMONIC: tone shadow woman critic glare utility brass scheme edge brisk enforce champion - user-local2: extra_hosts: - 'host.docker.internal:host-gateway' @@ -68,5 +64,4 @@ services: ERC20_NAME: ERC20Mock # RECIPIENT_PKD: 0x193a37cd7973373aceae05d133f3d69ab6e7ef2f4321461173871ec7611244e2,0x27234a8721e73c9aa160154ee63d2470101fc5fd841221eeb675a91ec2d66e78 RECIPIENT_PKD: '0x27234a8721e73c9aa160154ee63d2470101fc5fd841221eeb675a91ec2d66e78' - ZKP_MNEMONIC: - tiger victory velvet tank ritual column horse conduct athlete position soul shaft + ZKP_MNEMONIC: tiger victory velvet tank ritual column horse conduct athlete position soul shaft diff --git a/test/ping-pong/docker-compose.ropsten.yml b/test/ping-pong/docker-compose.ropsten.yml index f6e905b81..a0d0cf099 100644 --- a/test/ping-pong/docker-compose.ropsten.yml +++ b/test/ping-pong/docker-compose.ropsten.yml @@ -31,7 +31,6 @@ services: environment: BLOCKCHAIN_WS_HOST: ropsten1-ws.testnet.nightfall3.com BLOCKCHAIN_PORT: 80 - PROPOSER_ETHEREUM_SIGNING_KEY: 645ac79fa9fd87dd1cf30bdca51d326bd501cd328d6dbc9f5f517c7da0dafa6f user-local1: environment: @@ -46,7 +45,6 @@ services: ZKP_MNEMONIC: tone shadow woman critic glare utility brass scheme edge brisk enforce champion TX_WAIT: 120000 - user-local2: environment: BLOCKCHAIN_WS_HOST: ropsten1-ws.testnet.nightfall3.com diff --git a/test/ping-pong/docker-compose.standalone.ganache.yml b/test/ping-pong/docker-compose.standalone.ganache.yml index 74eea9ab6..406b763b9 100644 --- a/test/ping-pong/docker-compose.standalone.ganache.yml +++ b/test/ping-pong/docker-compose.standalone.ganache.yml @@ -13,3 +13,6 @@ services: --account="0x645ac79fa9fd87dd1cf30bdca51d326bd501cd328d6dbc9f5f517c7da0dafa6f,10000000000000000000000" --account="0xadf9b65664deaa27d37f2c3bae4f70ca22cbe9d956a1be5873770f6fd68df271,10000000000000000000000" --account="0xeed50965cbe8268a3ee0a24afc2f31c434a7d568bdff73a89783711c91ca1c67,10000000000000000000000" + --account="0x4775af73d6dc84a0ae76f8726bda4b9ecf187c377229cb39e1afa7a18236a69d,10000000000000000000000" + --account="0x4775af73d6dc84a0ae76f8726bda4b9ecf187c377229cb39e1afa7a18236a69e,10000000000000000000000" + --account="0xd42905d0582c476c4b74757be6576ec323d715a0c7dcff231b6348b7ab0190eb,10000000000000000000000" diff --git a/test/ping-pong/docker-compose.yml b/test/ping-pong/docker-compose.yml index 270cc94c4..f91825d09 100644 --- a/test/ping-pong/docker-compose.yml +++ b/test/ping-pong/docker-compose.yml @@ -33,7 +33,7 @@ services: OPTIMIST_HOST: optimist OPTIMIST_PORT: 80 USE_STUBS: 'false' # make sure this flag is the same as in deployer service - command: ['npm', 'run', 'dev'] + command: [ 'npm', 'run', 'dev' ] rabbitmq: image: rabbitmq @@ -61,7 +61,7 @@ services: TRANSACTIONS_PER_BLOCK: ${TRANSACTIONS_PER_BLOCK:-2} TIMBER_HOST: timber TIMBER_PORT: 80 - command: ['npm', 'run', 'dev'] + command: [ 'npm', 'run', 'dev' ] # Temporary container to deploy contracts and circuits and populate volumes deployer: @@ -109,9 +109,11 @@ services: environment: OPTIMIST_HOST: optimist OPTIMIST_WS_PORT: 8080 - OPTIMIST_HTTP_PORT: 80 + OPTIMIST_PORT: 80 BLOCKCHAIN_WS_HOST: blockchain1 BLOCKCHAIN_PORT: 8546 + CLIENT_HOST: client + CLIENT_PORT: 80 PROPOSER_PORT: 8080 PROPOSER_URL: http://proposer @@ -125,7 +127,7 @@ services: environment: OPTIMIST_HOST: optimist OPTIMIST_WS_PORT: 8080 - OPTIMIST_HTTP_PORT: 80 + OPTIMIST_PORT: 80 CLIENT_HOST: client CLIENT_PORT: 80 BLOCKCHAIN_WS_HOST: blockchain1 @@ -142,7 +144,7 @@ services: environment: OPTIMIST_HOST: optimist OPTIMIST_WS_PORT: 8080 - OPTIMIST_HTTP_PORT: 80 + OPTIMIST_PORT: 80 CLIENT_HOST: client CLIENT_PORT: 80 BLOCKCHAIN_WS_HOST: blockchain1 diff --git a/test/ping-pong/proposer/src/app.mjs b/test/ping-pong/proposer/src/app.mjs index 6df079d74..ff9a51d69 100644 --- a/test/ping-pong/proposer/src/app.mjs +++ b/test/ping-pong/proposer/src/app.mjs @@ -22,8 +22,4 @@ app.use( app.get('/healthcheck', (req, res) => res.sendStatus(200)); app.use('/proposer', proposer.router); -function setNf3Instance(nf3) { - proposer.setNf3Instance(nf3); -} - -export { app, setNf3Instance }; +export default app; diff --git a/test/ping-pong/proposer/src/index.mjs b/test/ping-pong/proposer/src/index.mjs index c15294a0b..49ceeaf08 100644 --- a/test/ping-pong/proposer/src/index.mjs +++ b/test/ping-pong/proposer/src/index.mjs @@ -4,9 +4,11 @@ Module that runs up as a proposer import config from 'config'; import logger from '../../../../common-files/utils/logger.mjs'; import Nf3 from '../../../../cli/lib/nf3.mjs'; -import { app, setNf3Instance } from './app.mjs'; +import app from './app.mjs'; -const { proposerEthereumSigningKey, optimistWsUrl, web3WsUrl, optimistBaseUrl } = config; +const environment = config.ENVIRONMENTS[process.env.ENVIRONMENT] || config.ENVIRONMENTS.localhost; + +const { mnemonics, signingKeys } = config.TEST_OPTIONS; const { PROPOSER_PORT = '', PROPOSER_URL = '' } = process.env; /** @@ -14,18 +16,15 @@ Does the preliminary setup and starts listening on the websocket */ async function startProposer() { logger.info('Starting Proposer...'); - const nf3 = new Nf3(proposerEthereumSigningKey, { - web3WsUrl, - optimistApiUrl: optimistBaseUrl, - optimistWsUrl, - }); - await nf3.init(undefined, 'optimist'); + const nf3 = new Nf3(signingKeys.proposer1, environment); + await nf3.init(mnemonics.proposer); + if (await nf3.healthcheck('optimist')) logger.info('Healthcheck passed'); else throw new Error('Healthcheck failed'); logger.info('Attempting to register proposer'); // let's see if the proposer has been registered before - const { proposers } = await nf3.getProposers(); const proposerUrl = PROPOSER_PORT !== '' ? `${PROPOSER_URL}:${PROPOSER_PORT}` : ''; + const { proposers } = await nf3.getProposers(); // if not, let's register them if (proposers.length === 0) { await nf3.registerProposer(proposerUrl); @@ -35,9 +34,8 @@ async function startProposer() { logger.info('Proposer registration complete'); } else logger.warn('Proposer appears to be registerd already'); if (PROPOSER_PORT !== '') { - setNf3Instance(nf3); + logger.debug('Proposer healthcheck up'); app.listen(PROPOSER_PORT); - logger.debug(`Proposer API up at URL ${PROPOSER_URL} and port ${PROPOSER_PORT}`); } // TODO subscribe to layer 1 blocks and call change proposer nf3.startProposer(); diff --git a/test/ping-pong/user-local/src/index.mjs b/test/ping-pong/user-local/src/index.mjs index 0c66c1186..5377772ac 100644 --- a/test/ping-pong/user-local/src/index.mjs +++ b/test/ping-pong/user-local/src/index.mjs @@ -9,36 +9,25 @@ import logger from '../../../../common-files/utils/logger.mjs'; import Nf3 from '../../../../cli/lib/nf3.mjs'; import { waitForSufficientBalance, retrieveL2Balance } from './utils.mjs'; -const { - zkpMnemonic, - userEthereumSigningKey, - optimistWsUrl, - web3WsUrl, - clientBaseUrl, - optimistBaseUrl, - TRANSACTIONS_PER_BLOCK, -} = config; +const environment = config.ENVIRONMENTS[process.env.ENVIRONMENT] || config.ENVIRONMENTS.localhost; + +const { mnemonics, signingKeys, txPerBlock, recipients } = config.TEST_OPTIONS; const { TEST_LENGTH, ERC20_NAME, TX_WAIT = 1000, IS_TEST_RUNNER = '' } = process.env; -const recipientPkd = process.env.RECIPIENT_PKD; // .split(','); /** Does the preliminary setup and starts listening on the websocket */ async function localTest() { logger.info('Starting local test...'); + logger.debug('ENVV', environment); const tokenType = 'ERC20'; const value = 1; const tokenId = '0x0000000000000000000000000000000000000000000000000000000000000000'; - const nf3 = new Nf3(userEthereumSigningKey, { - web3WsUrl, - clientApiUrl: clientBaseUrl, - optimistApiUrl: optimistBaseUrl, - optimistWsUrl, - }); + const nf3 = new Nf3(IS_TEST_RUNNER ? signingKeys.user1 : signingKeys.user2, environment); - await nf3.init(zkpMnemonic); + await nf3.init(IS_TEST_RUNNER ? mnemonics.user1 : mnemonics.user2); if (await nf3.healthcheck('client')) logger.info('Healthcheck passed'); else throw new Error('Healthcheck failed'); @@ -46,18 +35,15 @@ async function localTest() { const startBalance = await retrieveL2Balance(nf3); // Create a block of deposits - for (let i = 0; i < TRANSACTIONS_PER_BLOCK; i++) { + for (let i = 0; i < txPerBlock; i++) { await nf3.deposit(ercAddress, tokenType, value, tokenId); } // Create a block of transfer and deposit transactions - let offchain = false; for (let i = 0; i < TEST_LENGTH; i++) { await waitForSufficientBalance(nf3, value); try { - logger.info(`Transfer is sent offchain : ${offchain}`); - await nf3.transfer(offchain, ercAddress, tokenType, value, tokenId, recipientPkd); - offchain = !offchain; + await nf3.transfer(false, ercAddress, tokenType, value, tokenId, recipients.user1); } catch (err) { if (err.message.includes('No suitable commitments')) { // if we get here, it's possible that a block we are waiting for has not been proposed yet @@ -68,7 +54,7 @@ async function localTest() { } seconds and try one last time`, ); await new Promise(resolve => setTimeout(resolve, 10 * TX_WAIT)); - await nf3.transfer(false, ercAddress, tokenType, value, tokenId, recipientPkd); + await nf3.transfer(false, ercAddress, tokenType, value, tokenId, recipients.user1); } } await nf3.deposit(ercAddress, tokenType, value, tokenId); diff --git a/test/utils.mjs b/test/utils.mjs index e092df5a0..d849f4b09 100644 --- a/test/utils.mjs +++ b/test/utils.mjs @@ -2,13 +2,13 @@ import Web3 from 'web3'; import chai from 'chai'; import config from 'config'; +import logger from '../common-files/utils/logger.mjs'; import rand from '../common-files/utils/crypto/crypto-random.mjs'; const { expect } = chai; const { WEB3_PROVIDER_OPTIONS } = config; const ENVIRONMENT = config.ENVIRONMENTS[process.env.ENVIRONMENT] || config.ENVIRONMENTS.localhost; -const USE_INFURA = config.USE_INFURA === 'true'; const USE_ROPSTEN_NODE = config.USE_ROPSTEN_NODE === 'true'; export const topicEventMapping = { @@ -116,7 +116,7 @@ export class Web3Client { const accountAddress = await this.web3.eth.accounts.privateKeyToAccount(privateKey); nonce = await this.web3.eth.getTransactionCount(accountAddress.address); } - if (USE_INFURA || USE_ROPSTEN_NODE) { + if (USE_ROPSTEN_NODE) { // get gaslimt from latest block as gaslimt may vary gas = (await this.web3.eth.getBlock('latest')).gasLimit; const blockGasPrice = Number(await this.web3.eth.getGasPrice()); @@ -377,7 +377,7 @@ export const waitForSufficientBalance = (client, value) => { return new Promise(resolve => { async function isSufficientBalance() { const balance = await retrieveL2Balance(client); - if (process.env.VERBOSE) console.log(` Balance needed ${value}. Current balance ${balance}.`); + logger.debug(` Balance needed ${value}. Current balance ${balance}.`); if (balance < value) { await new Promise(resolving => setTimeout(resolving, 10000)); isSufficientBalance();