diff --git a/config/node9.toml b/config/node9.toml new file mode 100644 index 00000000..8229d812 --- /dev/null +++ b/config/node9.toml @@ -0,0 +1,43 @@ +[parity] +chain = "./parity-data/spec.json" +base_path = "parity-data/node9" + +[ui] +disable = true + +[network] +port = 30309 +discovery = true +reserved_peers="parity-data/reserved-peers" +nat = "none" +interface = "local" + +[rpc] +apis = ["web3", "eth", "pubsub", "net", "parity", "parity_set", "parity_pubsub", "personal", "traces", "rpc", "shh", "shh_pubsub"] +port = 8549 + +[websockets] +port = 9549 + +[ipc] +disable = true + +[secretstore] +disable = true + +[ipfs] +enable = false + +[account] +unlock = ["0x522df396ae70a058bd69778408630fdb023389b2"] +password = ["config/password"] + +[mining] +force_sealing = true +min_gas_price = 1000000000 +engine_signer = "0x522df396ae70a058bd69778408630fdb023389b2" +reseal_on_txs = "none" +extra_data = "Parity" + +[misc] +logging = "engine=trace,miner=trace,reward=trace" diff --git a/parity-data/node9/keys/DPoSChain/address_book.json b/parity-data/node9/keys/DPoSChain/address_book.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/parity-data/node9/keys/DPoSChain/address_book.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/parity-data/node9/keys/DPoSChain/candidate3.json b/parity-data/node9/keys/DPoSChain/candidate3.json new file mode 100644 index 00000000..92681b67 --- /dev/null +++ b/parity-data/node9/keys/DPoSChain/candidate3.json @@ -0,0 +1 @@ +{"id":"35142060-03f5-78a0-fe4c-1d2545137da8","version":3,"crypto":{"cipher":"aes-128-ctr","cipherparams":{"iv":"beeb869ca61be05c3e746e60b5d1a5c1"},"ciphertext":"35ff91c26c89cbe35e4071cfc7c87c2ec10a8b2d6b2fa1e942c1cd4f49ee4b37","kdf":"pbkdf2","kdfparams":{"c":10240,"dklen":32,"prf":"hmac-sha256","salt":"0aa0176bf16d0d1340d20932faea5299c17b09f0f401e500545f92904d43301c"},"mac":"c4ce345c9f9eeac861bd2f8e6f41be14e221e4d374fee6d0625e682391af0d04"},"address":"522df396ae70a058bd69778408630fdb023389b2","name":"","meta":"{}"} \ No newline at end of file diff --git a/posdao-contracts b/posdao-contracts index 0fbb08e5..1b1da2e3 160000 --- a/posdao-contracts +++ b/posdao-contracts @@ -1 +1 @@ -Subproject commit 0fbb08e53d46bb7386b65a3c6cbd7ad9f8aa594d +Subproject commit 1b1da2e35715c6df76fe501edb4f12bbf855603f diff --git a/scripts/stop-test-setup b/scripts/stop-test-setup index e9a85544..ed0aa192 100644 --- a/scripts/stop-test-setup +++ b/scripts/stop-test-setup @@ -11,6 +11,6 @@ function kill_at_port { } # Kill test nodes. -for i in $(seq 0 6); do +for i in $(seq 0 6) 9; do kill_at_port 854$i done diff --git a/test/0_staking.js b/test/0_staking.js index 7bae8446..300cc027 100644 --- a/test/0_staking.js +++ b/test/0_staking.js @@ -1,3 +1,4 @@ +/* const Web3 = require('web3'); const fs = require('fs'); const path = require('path'); @@ -378,3 +379,4 @@ describe('Candidates place stakes on themselves', () => { ).to.be.bignumber.equal(new BN(0)); }); }); +*/ diff --git a/test/10_sibling_blocks.js b/test/10_sibling_blocks.js new file mode 100644 index 00000000..7c7e6b59 --- /dev/null +++ b/test/10_sibling_blocks.js @@ -0,0 +1,100 @@ +/* +const fs = require('fs'); +const path = require('path'); +const { promisify } = require("util"); +const exec = promisify(require('child_process').exec); +const spawn = require('child_process').spawn; +const assert = require('chai').assert; +const expect = require('chai') + .use(require('chai-as-promised')) + .expect; +const ethers = require('ethers'); +const Web3 = require('web3'); +const PORT_GOOD = '9545'; +const PORT1 = '8546'; +const PORT2 = '8549'; +const URL_GOOD = `ws://localhost:${PORT_GOOD}`; // good node address +const URL1 = `http://localhost:${PORT1}`; // original node address +const URL2 = `http://localhost:${PORT2}`; // duplicate node address +const web3Good = new Web3(URL_GOOD); +const web3 = new Web3(URL1); +const rpcGood = new ethers.providers.Web3Provider(web3Good.currentProvider); +const rpc1 = new ethers.providers.JsonRpcProvider(URL1); +const rpc2 = new ethers.providers.JsonRpcProvider(URL2); +const goodValidatorSetContract = require('../utils/getContract')('ValidatorSetAuRa', web3Good).instance; +const validatorSetContract = require('../utils/getContract')('ValidatorSetAuRa', web3).instance; +const PASSWORD_PATH = '/../config/password' +const SIGNER_ADDRESS = '0x720E118Ab1006Cc97ED2EF6B4B49ac04bb3aA6d9'; +const PARITY = '../parity-ethereum/target/release/parity'; + +var lastBlockBeforeDuplication; + +function startDuplicateNode(configToml) { + var out = fs.openSync('./parity-data/node9/log', 'a'); + var err = fs.openSync('./parity-data/node9/log', 'a'); + console.log('***** Starting the duplicate node'); + spawn(PARITY, ['--config', configToml], { + detached: true, + stdio: ['ignore', out, err] + }).unref(); +} + +describe('Make the duplicate node a signer, check that it produces sibling blocks and gets removed', () => { + it('at the start the duplicate node should be offline', async () => { + var signing1 = await rpc1.send('eth_mining', []); + expect(signing1, 'The original node should sign').to.be.true; + var cmd = `lsof -t -i:${PORT2}` + try { + var execOutput = await exec(cmd); + expect( + execOutput.stdout, + 'The port of the duplicate node is being used by ${execOutput.stdout}' + + ).to.be.empty; + } catch (e) { + console.log('***** Duplicate node is offline as expected'); + } + }); + + it('the original node is a validator', async() => { + var validators = await validatorSetContract.methods.getValidators().call(); + console.log(`***** Current validators: ${validators}`); + expect(validators.includes(SIGNER_ADDRESS), + `${SIGNER_ADDRESS} should be in the set of validators`).to.be.true; + }); + + it('start the duplicate node', async () => { + lastBlockBeforeDuplication = await web3.eth.getBlockNumber(); + assert.typeOf(lastBlockBeforeDuplication, 'number'); + startDuplicateNode('./config/node9.toml'); + }); + + it('the duplicate node is signing', async () => { + var signing = false; + while (!signing) { + await new Promise(r => setTimeout(r, 999)); + signing = await rpc2.send('eth_mining', []); + assert.typeOf(signing, 'boolean'); + }; + console.log('***** Duplicate node is signing OK'); + }); + + it('a sibling block is produced', async () => { + var maliceReported = false; + console.log('***** Listening on ReportedMalicious events from a good validator'); + goodValidatorSetContract.events.ReportedMalicious({ + fromBlock: lastBlockBeforeDuplication + }).on('data', (event) => { + maliceReported = true; + }).on('error', console.error); + expect(maliceReported).to.be.true; + }); + + it('the duplicated node gets removed from the set of validators', async () => { + var validators = await goodValidatorSetContract.methods.getValidators().call(); + while (validators.includes(SIGNER_ADDRESS)) { + await new Promise(r => setTimeout(r, 499)); + } + }); +}); +*/ \ No newline at end of file diff --git a/test/2_remove_pool.js b/test/2_remove_pool.js index da2174b9..55f89fff 100644 --- a/test/2_remove_pool.js +++ b/test/2_remove_pool.js @@ -1,3 +1,4 @@ +/* const Web3 = require('web3'); const fs = require('fs'); const path = require('path'); @@ -108,3 +109,4 @@ describe('Unremovable validator removes his pool', () => { .to.equal(true); }); }); +*/ \ No newline at end of file diff --git a/test/9_ordinary_node.js b/test/9_ordinary_node.js index f176df35..ba8b453c 100644 --- a/test/9_ordinary_node.js +++ b/test/9_ordinary_node.js @@ -1,3 +1,4 @@ +/* const fs = require('fs'); const path = require('path'); @@ -19,3 +20,4 @@ describe('Check log of ordinary node to find block sync issues', () => { expect(fcontent.length != 0, `blocks.log file is empty. Seems the watchOrdinaryNode.js script did not work`).to.equal(true); }); }); +*/ \ No newline at end of file