Skip to content
This repository has been archived by the owner on Dec 16, 2021. It is now read-only.

feat: activate sporks during local setup #286

Merged
merged 1 commit into from
Mar 2, 2021
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
39 changes: 33 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
"homepage": "https://github.com/dashevo/mn-bootstrap#readme",
"dependencies": {
"@dashevo/dashcore-lib": "~0.19.21",
"@dashevo/dashd-rpc": "~2.0.2",
"@dashevo/dashd-rpc": "~2.1.1",
"@dashevo/dashpay-contract": "github:dashevo/dashpay-contract#bc4e9b2d0073e27bd716b3ae63ccfdd60d8c4f36",
"@dashevo/dpns-contract": "~0.3.0-dev.6",
"@dashevo/wallet-lib": "~7.18.0-dev.3",
Expand Down
11 changes: 11 additions & 0 deletions src/core/activateCoreSpork.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* @typedef activateCoreSpork
* @param {RpcClient} rpcClient
* @param {string} spork
* @returns {Promise<void>}
*/
async function activateCoreSpork(rpcClient, spork) {
await rpcClient.spork(spork, 0);
}

module.exports = activateCoreSpork;
30 changes: 30 additions & 0 deletions src/core/waitForCoreQuorum.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
const wait = require('../util/wait');

/**
* Wait Core to set quorum
*
* @typedef {waitForCoreQuorum}
* @param {RpcClient} rpcClient
* @return {Promise<void>}
*/
async function waitForCoreQuorum(rpcClient) {
let hasQuorums = false;

do {
const { result: quorums } = await rpcClient.quorum('list');

if (quorums) {
for (const quorum of Object.values(quorums)) {
if (quorum.length > 0) {
hasQuorums = true;
}
}
}

if (!hasQuorums) {
await wait(10000);
}
} while (!hasQuorums);
}

module.exports = waitForCoreQuorum;
6 changes: 6 additions & 0 deletions src/createDIContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ const waitForCoreSync = require('./core/waitForCoreSync');
const waitForBlocks = require('./core/waitForBlocks');
const waitForConfirmations = require('./core/waitForConfirmations');
const generateBlsKeys = require('./core/generateBlsKeys');
const activateCoreSpork = require('./core/activateCoreSpork');
const waitForCoreQuorum = require('./core/waitForCoreQuorum');

const createNewAddress = require('./core/wallet/createNewAddress');
const generateBlocks = require('./core/wallet/generateBlocks');
Expand All @@ -60,6 +62,7 @@ const resetNodeTaskFactory = require('./listr/tasks/resetNodeTaskFactory');
const configureCoreTaskFactory = require('./listr/tasks/setup/local/configureCoreTaskFactory');
const configureTenderdashTaskFactory = require('./listr/tasks/setup/local/configureTenderdashTaskFactory');
const initializePlatformTaskFactory = require('./listr/tasks/setup/local/initializePlatformTaskFactory');
const activateSporksTaskFactory = require('./listr/tasks/setup/local/activateSporksTaskFactory');

async function createDIContainer(options) {
const container = createAwilixContainer({
Expand Down Expand Up @@ -118,6 +121,8 @@ async function createDIContainer(options) {
waitForBlocks: asValue(waitForBlocks),
waitForConfirmations: asValue(waitForConfirmations),
generateBlsKeys: asValue(generateBlsKeys),
activateCoreSpork: asValue(activateCoreSpork),
waitForCoreQuorum: asValue(waitForCoreQuorum),
});

/**
Expand Down Expand Up @@ -159,6 +164,7 @@ async function createDIContainer(options) {
configureTenderdashTask: asFunction(configureTenderdashTaskFactory).singleton(),
initializePlatformTask: asFunction(initializePlatformTaskFactory).singleton(),
outputStatusOverview: asFunction(outputStatusOverviewFactory),
activateSporksTask: asFunction(activateSporksTaskFactory).singleton(),
});

return container;
Expand Down
4 changes: 1 addition & 3 deletions src/listr/tasks/resetNodeTaskFactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,7 @@ function resetNodeTaskFactory(
projectVolumeNames
.filter((volumeName) => !coreVolumeNames.includes(volumeName))
.map((volumeName) => `${composeProjectName}_${volumeName}`)
.map(async (volumeName) => {
return docker.getVolume(volumeName).remove();
}),
.map(async (volumeName) => docker.getVolume(volumeName).remove()),
);
},
},
Expand Down
62 changes: 62 additions & 0 deletions src/listr/tasks/setup/local/activateSporksTaskFactory.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
const { Listr } = require('listr2');
const getSeedNodeConfig = require('../../../../util/getSeedNodeConfig');

/**
*
* @param {activateCoreSpork} activateCoreSpork
* @param {waitForCoreQuorum} waitForCoreQuorum
* @param {createRpcClient} createRpcClient
* @return {activateSporksTask}
*/
function activateSporksTaskFactory(
activateCoreSpork,
waitForCoreQuorum,
createRpcClient,
) {
/**
* @typedef activateSporksTask
* @param {Config[]} configGroup
* @return {Listr}
*/
function activateSporksTask(configGroup) {
return new Listr([
{
title: 'Enable sporks',
task: async (ctx) => {
const seedConfig = getSeedNodeConfig(configGroup);

ctx.rpcClient = createRpcClient({
port: seedConfig.get('core.rpc.port'),
user: seedConfig.get('core.rpc.user'),
pass: seedConfig.get('core.rpc.password'),
});

const sporks = [
'SPORK_2_INSTANTSEND_ENABLED',
'SPORK_3_INSTANTSEND_BLOCK_FILTERING',
'SPORK_9_SUPERBLOCKS_ENABLED',
'SPORK_17_QUORUM_DKG_ENABLED',
'SPORK_19_CHAINLOCKS_ENABLED',
];

await Promise.all(
sporks.map((spork) => (
activateCoreSpork(ctx.rpcClient, spork))),
);
},
},
{
title: 'Waiting for quorums',
task: async (ctx) => {
const seedConfig = getSeedNodeConfig(configGroup);

await waitForCoreQuorum(ctx.rpcClient, seedConfig.get('network'));
},
},
]);
}

return activateSporksTask;
}

module.exports = activateSporksTaskFactory;
26 changes: 26 additions & 0 deletions src/listr/tasks/setup/local/configureCoreTaskFactory.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
const { Listr } = require('listr2');
const {
PrivateKey,
} = require('@dashevo/dashcore-lib');
const isSeedNode = require('../../../../util/isSeedNode');

/**
* @param {resolveDockerHostIp} resolveDockerHostIp
Expand All @@ -7,6 +11,8 @@ const { Listr } = require('listr2');
* @param {startCore} startCore
* @param {generateBlocks} generateBlocks
* @param {waitForCoreSync} waitForCoreSync
* @param {activateCoreSpork} activateCoreSpork
* @param {waitForCoreQuorum} waitForCoreQuorum
* @param {generateToAddressTask} generateToAddressTask
* @param {registerMasternodeTask} registerMasternodeTask
* @return {configureCoreTask}
Expand All @@ -18,6 +24,8 @@ function configureCoreTaskFactory(
startCore,
generateBlocks,
waitForCoreSync,
activateCoreSpork,
waitForCoreQuorum,
generateToAddressTask,
registerMasternodeTask,
) {
Expand All @@ -36,17 +44,35 @@ function configureCoreTaskFactory(
ctx.hostDockerInternalIp = await resolveDockerHostIp();
}

const network = configGroup[0].get('network');
const sporkPrivKey = new PrivateKey(undefined, network);
const sporkAddress = sporkPrivKey.toAddress(network).toString();

const p2pSeeds = configGroup.map((config) => ({
host: ctx.hostDockerInternalIp,
port: config.get('core.p2p.port'),
}));

configGroup.forEach((config, i) => {
// seeds
config.set(
'core.p2p.seeds',
p2pSeeds.filter((seed, index) => index !== i),
);

// sporks
config.set(
'core.spork.address',
sporkAddress,
);

if (isSeedNode(config)) {
config.set(
'core.spork.privateKey',
sporkPrivKey.toWIF(),
);
}

// Write configs
const configFiles = renderServiceTemplates(config);
writeServiceConfigs(config.getName(), configFiles);
Expand Down
39 changes: 33 additions & 6 deletions src/listr/tasks/setup/local/initializePlatformTaskFactory.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,38 @@
const { Listr } = require('listr2');

const wait = require('../../../../util/wait');
const baseConfig = require('../../../../../configs/system/base');
const isSeedNode = require('../../../../util/isSeedNode');
const getSeedNodeConfig = require('../../../../util/getSeedNodeConfig');

/**
*
* @param {startNodeTask} startNodeTask
* @param {initTask} initTask
* @param {activateSporksTask} activateSporksTask
* @param {DockerCompose} dockerCompose
* @return {initializePlatformTask}
*/
function initializePlatformTaskFactory(
startNodeTask,
initTask,
activateSporksTask,
dockerCompose,
) {
/**
* @param {Config} config
* @return {boolean}
* @typedef initializePlatformTask
* @param {Config[]} configGroup
* @return {Listr}
*/
function isSeedNode(config) {
return config.getName() === 'local_seed';
}

function initializePlatformTask(configGroup) {
return new Listr([
{
task: () => {
// to activate sporks faster, set miner interval to 2s
const seedNodeConfig = getSeedNodeConfig(configGroup);
seedNodeConfig.set('core.miner.interval', '2s');
},
},
{
title: 'Starting nodes',
task: async (ctx) => {
Expand All @@ -40,9 +56,20 @@ function initializePlatformTaskFactory(
title: 'Wait 20 seconds to ensure all services are running',
task: () => wait(20000),
},
{
title: 'Activate sporks',
task: () => activateSporksTask(configGroup),
},
{
task: () => initTask(configGroup[0]),
},
{
task: () => {
// back to default
const seedNodeConfig = getSeedNodeConfig(configGroup);
seedNodeConfig.set('core.miner.interval', baseConfig.core.miner.interval);
},
},
{
title: 'Stopping nodes',
task: async () => {
Expand Down
9 changes: 9 additions & 0 deletions src/util/getSeedNodeConfig.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* @param {Config[]} configGroup
* @return {Config}
*/
function getSeedNodeConfig(configGroup) {
return configGroup.find((config) => config.getName() === 'local_seed');
}

module.exports = getSeedNodeConfig;
9 changes: 9 additions & 0 deletions src/util/isSeedNode.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* @param {Config} config
* @return {boolean}
*/
function isSeedNode(config) {
return config.getName() === 'local_seed';
}

module.exports = isSeedNode;
2 changes: 2 additions & 0 deletions templates/dashd.conf.template
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ llmq-qvvec-sync=llmq_100_67
{{?? it.network === 'local'}}
regtest=1
[regtest]
sporkaddr={{=it.core.spork.address}}
{{? it.core.spork.privateKey}}sporkkey={{=it.core.spork.privateKey}}{{?}}
{{~it.core.p2p.seeds :seed}}
addnode={{=seed.host}}:{{=seed.port}}{{~}}
{{?? it.network === 'devnet'}}
Expand Down