Skip to content

Commit

Permalink
Separate node accounts (#315)
Browse files Browse the repository at this point in the history
* Division of a node's account into staking and operating

* Fix staking/operating address usage

* Fix retireApollo action

* Fix Multiplexer tests

* Fix units tests

* Added safe onboarding tests

* Bump version

* Update Ganache version

Co-authored-by: Andrii Rozinko <a.rozinko@minerall.io>
  • Loading branch information
AndrewAR2 and Andrii Rozinko authored Feb 28, 2022
1 parent f64fcc5 commit 2697ce5
Show file tree
Hide file tree
Showing 11 changed files with 2,042 additions and 4,681 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "ambrosus-node-contracts",
"author": "Ambrosus",
"description": "Smart contracts used in AMB-NET",
"version": "0.0.90",
"version": "0.0.91",
"license": "MPL-2.0-no-copyleft-exception",
"repository": "git@github.com:ambrosus/ambrosus-node-contracts.git",
"main": "dist/index.js",
Expand Down Expand Up @@ -52,7 +52,7 @@
"eslint-plugin-header": "^3.1.1",
"eslint-plugin-import": "^2.23.4",
"eslint-plugin-mocha": "^8.2.0",
"ganache-core": "^2.13.2",
"ganache": "^7.0.0",
"memdown": "^6.0.0",
"mocha": "^8.4.0",
"sinon": "^11.1.1",
Expand Down
24 changes: 22 additions & 2 deletions src/actions/pool_actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,34 @@ export default class PoolActions {
const id = await contract.methods.id().call();
const active = await contract.methods.active().call();
const totalStake = await contract.methods.totalStake().call();
const nodesCount = await contract.methods.getNodesCount().call();
console.log(id, active ? 'active' : ' ', name, address, nodesCount, this.web3.utils.fromWei(totalStake, 'ether'));
const nodeStake = await contract.methods.nodeStake().call();
const nodesCount = +await contract.methods.getNodesCount().call();
let service;
try {
service = await contract.methods.service().call();
// eslint-disable-next-line no-empty
} catch (error) {
}
console.log(id, active ? 'active' : ' ', name, address, this.web3.utils.fromWei(nodeStake, 'ether'), nodesCount, this.web3.utils.fromWei(totalStake, 'ether'), service);
}
} else {
console.log('No pools found');
}
}

async getPoolNodesList(poolAddress) {
const contract = await loadContract(this.web3, PoolJson.abi, poolAddress);
const count = await contract.methods.getNodesCount().call();
if (+count > 0) {
const nodess = await contract.methods.getNodes(0, count).call();
for (const address of nodess) {
console.log(address);
}
} else {
console.log('Empty pool');
}
}

async activate(address, value) {
const contract = await loadContract(this.web3, PoolJson.abi, address);
console.log(await contract.methods.activate().send({gas: DEFAULT_GAS, value, from: this.web3.eth.defaultAccount}));
Expand Down
9 changes: 9 additions & 0 deletions src/tasks/pooling.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ export default class PoolingTask extends TaskBase {
await this.activatePool(options[0], options[1]);
} else if (command === 'deactivate') {
await this.deactivatePool(options[0]);
} else if (command === 'nodes') {
await this.poolNodes(options[0]);
} else if (command === 'stake') {
await this.stake(options[0], options[1]);
} else if (command === 'unstake') {
Expand Down Expand Up @@ -89,6 +91,13 @@ export default class PoolingTask extends TaskBase {
console.error('Wrong address, use: yarn task pooling deactivate [pool address]');
}

async poolNodes(poolAddress) {
if (utils.isAddress(poolAddress)) {
return this.poolActions.getPoolNodesListdeactivate(poolAddress);
}
console.error('Wrong address, use: yarn task pooling nodes [pool address]');
}

async stake(poolAddress, value) {
if (utils.isAddress(poolAddress)) {
return this.poolActions.stake(poolAddress, this.poolActions.web3.utils.toWei(value, 'ether'));
Expand Down
31 changes: 21 additions & 10 deletions src/utils/web3_tools.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,26 +28,37 @@ function getDefaultGanacheOptions(secretKey) {
throw 'Secret key not defined';
}
return {
accounts: [
{
balance: '10000000000000000000000000000000000',
secretKey
},
...Array(9).fill({balance: '10000000000000000000000000000000000'})
],
vmErrorsOnRPCResponse: false
wallet: {
defaultBalance: 1000000000,
accounts: [
{
balance: '0x1ed09bead87c0378d8e6400000000',
secretKey
},
...Array(9).fill({balance: '0x1ed09bead87c0378d8e64000000000'})
]
},
logging: {
logger: {
log: () => {} // don't do anything
}
},
chain: {
hardfork: 'istanbul',
vmErrorsOnRPCResponse: false
}
};
}

export async function createGanacheServer(secretKey) {
const Ganache = require('ganache-core');
const Ganache = require('ganache');
const server = Ganache.server(getDefaultGanacheOptions(secretKey));
await server.listen(DEFAULT_PORT);
}

function createGanacheProvider(secretKey) {
// import in code with purpose:D
const Ganache = require('ganache-core');
const Ganache = require('ganache');
const memdown = require('memdown');
return Ganache.provider({
...getDefaultGanacheOptions(secretKey),
Expand Down
8 changes: 4 additions & 4 deletions test/contracts/consensus/block_rewards.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,16 +120,16 @@ describe('Block rewards contract', () => {
});

it('increases the total shares counter', async () => {
addBeneficiary(contract, owner, exampleBeneficiaries[0], '1002');
await addBeneficiary(contract, owner, exampleBeneficiaries[0], '1002');
expect(await totalShares(contract, owner)).to.equal('1002');
addBeneficiary(contract, owner, exampleBeneficiaries[1], '2093');
await addBeneficiary(contract, owner, exampleBeneficiaries[1], '2093');
expect(await totalShares(contract, owner)).to.equal('3095');
});

it('increases the beneficiary counter', async () => {
addBeneficiary(contract, owner, exampleBeneficiaries[0], '1002');
await addBeneficiary(contract, owner, exampleBeneficiaries[0], '1002');
expect(await beneficiaryCount(contract, owner)).to.equal('1');
addBeneficiary(contract, owner, exampleBeneficiaries[1], '2093');
await addBeneficiary(contract, owner, exampleBeneficiaries[1], '2093');
expect(await beneficiaryCount(contract, owner)).to.equal('2');
});

Expand Down
4 changes: 2 additions & 2 deletions test/contracts/front/challenges.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ describe('Challenges Contract', () => {
const startChallenge = async (sheltererId, bundleId, challengerId, fee) => challenges.methods.start(sheltererId, bundleId).send({from: challengerId, value: fee});
const startChallengeForSystem = async (uploaderId, bundleId, challengeCount, challengerId, fee) => challenges.methods.startForSystem(uploaderId, bundleId, challengeCount).send({from: challengerId, value: fee});
const resolveChallenge = async (challengeId, resolverId) => challenges.methods.resolve(challengeId).send({from: resolverId});
const markChallengeAsExpired = async (challengeId, marker) => challenges.methods.markAsExpired(challengeId).send({from: marker, gasPrice: '0'});
const markChallengeAsExpired = async (challengeId, marker) => challenges.methods.markAsExpired(challengeId).send({from: marker, gasPrice: '0x0'});

const getChallengeId = async (sheltererId, bundleId) => challenges.methods.getChallengeId(sheltererId, bundleId).call();
const getChallengeSequenceNumber = async (challengeId) => challenges.methods.getChallengeSequenceNumber(challengeId).call();
Expand All @@ -99,7 +99,7 @@ describe('Challenges Contract', () => {
const setNumberOfStakers = async (numberOfStakers) => atlasStakeStore.methods.setNumberOfStakers(numberOfStakers).send({from: context});
const removeLastStaker = async (nodeId, amount) => atlasStakeStore.methods.removeLastStaker(nodeId, amount).send({from: context});
const addShelterer = async (bundleId, sheltererId, shelteringReward) => sheltering.methods.addShelterer(bundleId, sheltererId).send({from: context, value: shelteringReward});
const onboardAsAtlas = async(nodeUrl, nodeAddress, depositValue) => roles.methods.onboardAsAtlas(nodeUrl).send({from: nodeAddress, value: depositValue, gasPrice: '0'});
const onboardAsAtlas = async(nodeUrl, nodeAddress, depositValue) => roles.methods.onboardAsAtlas(nodeUrl).send({from: nodeAddress, value: depositValue, gasPrice: '0x0'});

const getShelteringExpirationDate = async(bundleId, sheltererId) => sheltering.methods.getShelteringExpirationDate(bundleId, sheltererId).call();
const getFeeForChallenge = async (storagePeriods) => fees.methods.getFeeForChallenge(storagePeriods).call();
Expand Down
2 changes: 1 addition & 1 deletion test/contracts/front/roles.js
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,7 @@ describe('Roles Contract', () => {
const newUrl = 'https://yahoo.com';

it('correctly sets new URL', async () => {
onboardAsAtlas(oldUrl, atlas1, ATLAS1_STAKE);
await onboardAsAtlas(oldUrl, atlas1, ATLAS1_STAKE);
expect(await getUrl(atlas1)).to.equal(oldUrl);
await setUrl(atlas1, newUrl);
expect(await getUrl(atlas1)).to.equal(newUrl);
Expand Down
22 changes: 10 additions & 12 deletions test/contracts/front/upload.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {expectEventEmission} from '../../helpers/web3EventObserver';
import BN from 'bn.js';

export const COINBASE = '0x0000000000000000000000000000000000000000';
export const BLOCK_REWARD = utils.toWei(new BN(3));
export const BLOCK_REWARD = new BN(utils.toWei('3'));

chai.use(chaiEmitEvents);

Expand All @@ -47,12 +47,10 @@ describe('Upload Contract', () => {
let developer;

const bn10 = new BN(10);
const developerFee = new BN(333333);
const nonDeveloperFee = () => fee.sub(fee.mul(developerFee).div(new BN(1000000))).div(bn10)
.mul(bn10);
const developerFeeRate = new BN(300000);
const developerFee = () => fee.mul(developerFeeRate).div(new BN(1000000));
const expectedMinersFee = () => fee.mul(new BN(3)).div(bn10);
const expectedDeveloperFee = () => fee.sub(nonDeveloperFee());
const expectedMinersWithoutDeveloperFee = () => nonDeveloperFee().mul(new BN(3))
const expectedMinersWithoutDeveloperFee = () => fee.sub(developerFee()).mul(new BN(3))
.div(bn10);
const registerBundle = (bundleId, storagePeriods, uploader, fee) => uploads.methods.registerBundle(bundleId, storagePeriods).send({from: uploader, value: fee, gasPrice: '0'});
const setDeveloper = (developer, from = hermes) => fees.methods.setDeveloper(developer).send({from, gasPrice: '0'});
Expand Down Expand Up @@ -141,22 +139,22 @@ describe('Upload Contract', () => {
const balanceBefore = new BN(await web3.eth.getBalance(COINBASE));
await registerBundle(bundleId, 1, hermes, fee);
const balanceAfter = new BN(await web3.eth.getBalance(COINBASE));
const actualFee = balanceAfter.sub(balanceBefore).sub(BLOCK_REWARD);
expect(actualFee.eq(expectedMinersFee().sub(new BN('1000000000000000000')))).to.be.true;
const actualFee = balanceAfter.sub(balanceBefore);
expect(actualFee.eq(BLOCK_REWARD)).to.be.true;
});

it('Pay fee to miner and developer', async () => {
await setDeveloper(developer);
await setDeveloperUploadFee(developerFee);
await setDeveloperUploadFee(developerFeeRate);
const minerBalanceBefore = new BN(await web3.eth.getBalance(COINBASE));
const developerBalanceBefore = new BN(await web3.eth.getBalance(developer));
await registerBundle(bundleId, 1, hermes, fee);
const minerBalanceAfter = new BN(await web3.eth.getBalance(COINBASE));
const developerBalanceAfter = new BN(await web3.eth.getBalance(developer));
const actualMinerFee = minerBalanceAfter.sub(minerBalanceBefore).sub(BLOCK_REWARD);
expect(actualMinerFee.eq(expectedMinersWithoutDeveloperFee().sub(new BN('1000000000000000000')))).to.be.true;
const actualMinerFee = minerBalanceAfter.sub(minerBalanceBefore);
const actualDeveloperFee = developerBalanceAfter.sub(developerBalanceBefore);
expect(actualDeveloperFee.eq(expectedDeveloperFee())).to.be.true;
expect(actualMinerFee.eq(expectedMinersWithoutDeveloperFee())).to.be.true;
expect(actualDeveloperFee.eq(developerFee())).to.be.true;
});

it('Emits event signalizing payout of miner fee', async () => {
Expand Down
2 changes: 1 addition & 1 deletion test/mocharc.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
"test/mocha_env.js"
],
"recursive": true,
"timeout": 10000
"timeout": 30000
}
15 changes: 12 additions & 3 deletions test_cli/test_cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ This Source Code Form is subject to the terms of the Mozilla Public License, v.
This Source Code Form is “Incompatible With Secondary Licenses”, as defined by the Mozilla Public License, v. 2.0.
*/

const Ganache = require('ganache-core');
const Ganache = require('ganache');
const {exec} = require('child_process');
const fs = require('fs');
const dotenv = require('dotenv');
Expand Down Expand Up @@ -40,14 +40,23 @@ const printError = (message) => console.error('\x1b[31m', message, '\x1b[0m');

const startGanacheServer = (privateKeys) => new Promise((resolve, reject) => {
const accountRequests = privateKeys.map((value) => ({
balance: '10000000000000000000000000000000000',
balance: '0x1ed09bead87c0378d8e6400000000',
secretKey: value
}));
const server = Ganache.server({
defaultBalance: 1000000000,
accounts: [
...accountRequests,
...Array(9).fill({balance: '10000000000000000000000000000000000'})
...Array(9).fill({balance: '0x1ed09bead87c0378d8e6400000000'})
],
logging: {
logger: {
log: () => {} // don't do anything
}
},
chain: {
hardfork: 'istanbul'
},
blockTime: 1 // add automatic mining over time
});
server.listen(PORT, (err) => {
Expand Down
Loading

0 comments on commit 2697ce5

Please sign in to comment.