From 80df04d0c287afc49234e7c91c838e6c300f52fa Mon Sep 17 00:00:00 2001
From: Ivan Shumkov <ivan@shumkov.ru>
Date: Tue, 29 Oct 2024 13:35:36 +0700
Subject: [PATCH 1/5] fix: wrong migration version

---
 .../dashmate/configs/getConfigFileMigrationsFactory.js     | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/packages/dashmate/configs/getConfigFileMigrationsFactory.js b/packages/dashmate/configs/getConfigFileMigrationsFactory.js
index 51c8834625..ce45406b25 100644
--- a/packages/dashmate/configs/getConfigFileMigrationsFactory.js
+++ b/packages/dashmate/configs/getConfigFileMigrationsFactory.js
@@ -1030,12 +1030,7 @@ export default function getConfigFileMigrationsFactory(homeDir, defaultConfigs)
             if (options.network === NETWORK_TESTNET && name !== 'base') {
               options.platform.drive.tenderdash.p2p.seeds = testnet.get('platform.drive.tenderdash.p2p.seeds');
             }
-          });
-        return configFile;
-      },
-      '1.3.0-dev.3': (configFile) => {
-        Object.entries(configFile.configs)
-          .forEach(([, options]) => {
+
             if ([NETWORK_LOCAL, NETWORK_TESTNET, NETWORK_DEVNET].includes(options.network)) {
               options.core.docker.image = 'dashpay/dashd:22.0.0-nightly.2024.10.29';
             }

From 176d00934cc113931420a2550a7c07be6c140e7d Mon Sep 17 00:00:00 2001
From: Ivan Shumkov <ivan@shumkov.ru>
Date: Tue, 29 Oct 2024 13:59:41 +0700
Subject: [PATCH 2/5] chore: remove `deprecatedrpc=hpmn`

---
 packages/dashmate/templates/core/dash.conf.dot | 1 -
 1 file changed, 1 deletion(-)

diff --git a/packages/dashmate/templates/core/dash.conf.dot b/packages/dashmate/templates/core/dash.conf.dot
index cbc0b93373..a51b604b06 100644
--- a/packages/dashmate/templates/core/dash.conf.dot
+++ b/packages/dashmate/templates/core/dash.conf.dot
@@ -31,7 +31,6 @@ debuglogfile=/var/log/dash/debug.log
 # JSON RPC
 server=1
 rpcwallet=main
-deprecatedrpc=hpmn
 rpcworkqueue=64
 rpcthreads=16
 rpcwhitelistdefault=0

From d6f2d3b0758ef1e898bdf8161c824220744d8a92 Mon Sep 17 00:00:00 2001
From: Ivan Shumkov <ivan@shumkov.ru>
Date: Tue, 29 Oct 2024 22:59:12 +0700
Subject: [PATCH 3/5] pref(dashmate): simplify local network setup process

---
 .../setup/local/configureCoreTaskFactory.js   | 213 +++---------------
 1 file changed, 33 insertions(+), 180 deletions(-)

diff --git a/packages/dashmate/src/listr/tasks/setup/local/configureCoreTaskFactory.js b/packages/dashmate/src/listr/tasks/setup/local/configureCoreTaskFactory.js
index d059e9c860..920038d877 100644
--- a/packages/dashmate/src/listr/tasks/setup/local/configureCoreTaskFactory.js
+++ b/packages/dashmate/src/listr/tasks/setup/local/configureCoreTaskFactory.js
@@ -93,9 +93,40 @@ export default function configureCoreTaskFactory(
               },
             },
             {
-              title: 'Activating DIP3',
+              title: 'Create wallet',
+              task: async () => {
+                const disablePrivateKeys = false;
+                const createBlankWallet = false;
+                const walletPassphrase = '';
+                const avoidReuse = false;
+                const loadOnStartup = true;
+                const descriptors = false;
+
+                await ctx.coreService.getRpcClient().createWallet(
+                  'main',
+                  disablePrivateKeys,
+                  createBlankWallet,
+                  walletPassphrase,
+                  avoidReuse,
+                  descriptors,
+                  loadOnStartup,
+                );
+              },
+            },
+            {
+              title: 'Generating funds to use as a collateral for masternodes',
+              task: () => {
+                const amount = HPMN_COLLATERAL_AMOUNT * configGroup.length;
+                return generateToAddressTask(
+                  configGroup.find((c) => c.getName() === 'local_seed'),
+                  amount,
+                );
+              },
+            },
+            {
+              title: 'Activating forks',
               task: () => new Observable(async (observer) => {
-                const dip3ActivationHeight = 1000;
+                const dip3ActivationHeight = 901;
                 const blocksToGenerateInOneStep = 10;
 
                 let blocksGenerated = 0;
@@ -126,37 +157,6 @@ export default function configureCoreTaskFactory(
                 return this;
               }),
             },
-            {
-              title: 'Create wallet',
-              task: async () => {
-                const disablePrivateKeys = false;
-                const createBlankWallet = false;
-                const walletPassphrase = '';
-                const avoidReuse = false;
-                const loadOnStartup = true;
-                const descriptors = false;
-
-                await ctx.coreService.getRpcClient().createWallet(
-                  'main',
-                  disablePrivateKeys,
-                  createBlankWallet,
-                  walletPassphrase,
-                  avoidReuse,
-                  descriptors,
-                  loadOnStartup,
-                );
-              },
-            },
-            {
-              title: 'Generating funds to use as a collateral for masternodes',
-              task: () => {
-                const amount = HPMN_COLLATERAL_AMOUNT * configGroup.length;
-                return generateToAddressTask(
-                  configGroup.find((c) => c.getName() === 'local_seed'),
-                  amount,
-                );
-              },
-            },
             {
               title: 'Register masternodes',
               task: async () => {
@@ -276,51 +276,6 @@ export default function configureCoreTaskFactory(
                 );
               },
             },
-            {
-              title: 'Wait for nodes to have the same sporks',
-              task: () => waitForNodesToHaveTheSameSporks(ctx.coreServices),
-            },
-            {
-              title: 'Activating DIP8 to enable ChainLocks',
-              task: () => new Observable(async (observer) => {
-                let isDip8Activated = false;
-                let blockchainInfo;
-
-                let blocksGenerated = 0;
-
-                const blocksToGenerateInOneStep = 10;
-
-                do {
-                  ({
-                    result: blockchainInfo,
-                  } = await ctx.seedCoreService.getRpcClient().getBlockchainInfo());
-
-                  isDip8Activated = blockchainInfo.softforks.dip0008.active;
-
-                  if (isDip8Activated) {
-                    break;
-                  }
-
-                  await generateBlocks(
-                    ctx.seedCoreService,
-                    blocksToGenerateInOneStep,
-                    NETWORK_LOCAL,
-                    // eslint-disable-next-line no-loop-func
-                    (blocks) => {
-                      blocksGenerated += blocks;
-
-                      observer.next(`${blocksGenerated} blocks generated`);
-                    },
-                  );
-                } while (!isDip8Activated);
-
-                observer.next(`DIP8 has been activated at height ${blockchainInfo.softforks.dip0008.height}`);
-
-                observer.complete();
-
-                return this;
-              }),
-            },
             {
               title: 'Wait for nodes to have the same height',
               task: () => waitForNodesToHaveTheSameHeight(
@@ -347,108 +302,6 @@ export default function configureCoreTaskFactory(
               title: 'Wait for quorums to be enabled',
               task: () => enableCoreQuorumsTask(),
             },
-            {
-              title: 'Activating V20 fork',
-              task: () => new Observable(async (observer) => {
-                let isV20Activated = false;
-                let blockchainInfo;
-
-                let blocksGenerated = 0;
-
-                const blocksToGenerateInOneStep = 10;
-
-                do {
-                  ({
-                    result: blockchainInfo,
-                  } = await ctx.seedCoreService.getRpcClient().getBlockchainInfo());
-
-                  isV20Activated = blockchainInfo.softforks && blockchainInfo.softforks.v20
-                    && blockchainInfo.softforks.v20.active;
-                  if (isV20Activated) {
-                    break;
-                  }
-
-                  await generateBlocks(
-                    ctx.seedCoreService,
-                    blocksToGenerateInOneStep,
-                    NETWORK_LOCAL,
-                    // eslint-disable-next-line no-loop-func
-                    (blocks) => {
-                      blocksGenerated += blocks;
-
-                      observer.next(`${blocksGenerated} blocks generated`);
-                    },
-                  );
-                } while (!isV20Activated);
-
-                observer.next(`V20 fork has been activated at height ${blockchainInfo.softforks.v20.height}`);
-
-                observer.complete();
-
-                return this;
-              }),
-            },
-            {
-              title: 'Wait for nodes to have the same height',
-              task: () => waitForNodesToHaveTheSameHeight(
-                ctx.rpcClients,
-                WAIT_FOR_NODES_TIMEOUT,
-              ),
-            },
-            {
-              title: 'Enable EHF spork',
-              task: async () => new Observable(async (observer) => {
-                const seedRpcClient = ctx.seedCoreService.getRpcClient();
-                const {
-                  result: initialCoreChainLockedHeight,
-                } = await seedRpcClient.getBlockCount();
-
-                await activateCoreSpork(
-                  seedRpcClient,
-                  'SPORK_24_TEST_EHF',
-                  initialCoreChainLockedHeight,
-                );
-
-                let isEhfActivated = false;
-                let blockchainInfo;
-
-                let blocksGenerated = 0;
-
-                const blocksToGenerateInOneStep = 48;
-
-                do {
-                  ({
-                    result: blockchainInfo,
-                  } = await ctx.seedCoreService.getRpcClient().getBlockchainInfo());
-
-                  isEhfActivated = blockchainInfo.softforks && blockchainInfo.softforks.mn_rr
-                    && blockchainInfo.softforks.mn_rr.active;
-                  if (isEhfActivated) {
-                    break;
-                  }
-
-                  await ctx.bumpMockTime(blocksToGenerateInOneStep);
-
-                  await generateBlocks(
-                    ctx.seedCoreService,
-                    blocksToGenerateInOneStep,
-                    NETWORK_LOCAL,
-                    // eslint-disable-next-line no-loop-func
-                    (blocks) => {
-                      blocksGenerated += blocks;
-
-                      observer.next(`${blocksGenerated} blocks generated`);
-                    },
-                  );
-                } while (!isEhfActivated);
-
-                observer.next(`EHF has been activated at height ${blockchainInfo.softforks.mn_rr.height}`);
-
-                observer.complete();
-
-                return this;
-              }),
-            },
             {
               title: 'Wait for nodes to have the same height',
               task: () => waitForNodesToHaveTheSameHeight(

From c6bfcc1d4b592c42d8783530e2485364f7fb40ba Mon Sep 17 00:00:00 2001
From: Ivan Shumkov <ivan@shumkov.ru>
Date: Wed, 30 Oct 2024 19:57:37 +0700
Subject: [PATCH 4/5] fix: mn_rr activated before we have quorums

---
 packages/dashmate/templates/core/dash.conf.dot | 1 +
 1 file changed, 1 insertion(+)

diff --git a/packages/dashmate/templates/core/dash.conf.dot b/packages/dashmate/templates/core/dash.conf.dot
index a51b604b06..c63987d4ae 100644
--- a/packages/dashmate/templates/core/dash.conf.dot
+++ b/packages/dashmate/templates/core/dash.conf.dot
@@ -92,6 +92,7 @@ fallbackfee=0.00001
 {{?? it.network === 'local'}}
 regtest=1
 [regtest]
+testactivationheight=mn_rr@1000
 {{? it.core.spork.address}}sporkaddr={{=it.core.spork.address}}{{?}}
 {{? it.core.spork.privateKey}}sporkkey={{=it.core.spork.privateKey}}{{?}}
 {{? it.core.miner.mediantime}}mocktime={{=it.core.miner.mediantime}}{{?}}

From 9f01b42b0e12db114d1ac2fcf480861403885afd Mon Sep 17 00:00:00 2001
From: Ivan Shumkov <ivan@shumkov.ru>
Date: Wed, 30 Oct 2024 22:02:19 +0700
Subject: [PATCH 5/5] chore: make sure we activated mn_rr

---
 .../setup/local/configureCoreTaskFactory.js   | 44 ++++++++++++++++++-
 1 file changed, 42 insertions(+), 2 deletions(-)

diff --git a/packages/dashmate/src/listr/tasks/setup/local/configureCoreTaskFactory.js b/packages/dashmate/src/listr/tasks/setup/local/configureCoreTaskFactory.js
index 920038d877..522509b739 100644
--- a/packages/dashmate/src/listr/tasks/setup/local/configureCoreTaskFactory.js
+++ b/packages/dashmate/src/listr/tasks/setup/local/configureCoreTaskFactory.js
@@ -2,7 +2,6 @@ import { Listr } from 'listr2';
 import { Observable } from 'rxjs';
 import DashCoreLib from '@dashevo/dashcore-lib';
 import waitForNodesToHaveTheSameHeight from '../../../../core/waitForNodesToHaveTheSameHeight.js';
-import waitForNodesToHaveTheSameSporks from '../../../../core/waitForNodesToHaveTheSameSporks.js';
 
 import { NETWORK_LOCAL, HPMN_COLLATERAL_AMOUNT } from '../../../../constants.js';
 
@@ -124,7 +123,7 @@ export default function configureCoreTaskFactory(
               },
             },
             {
-              title: 'Activating forks',
+              title: 'Activating v19 and v20',
               task: () => new Observable(async (observer) => {
                 const dip3ActivationHeight = 901;
                 const blocksToGenerateInOneStep = 10;
@@ -309,6 +308,47 @@ export default function configureCoreTaskFactory(
                 WAIT_FOR_NODES_TIMEOUT,
               ),
             },
+            {
+              title: 'Activating v21 fork',
+              task: () => new Observable(async (observer) => {
+                const dip3ActivationHeight = 1001;
+                const blocksToGenerateInOneStep = 10;
+
+                let blocksGenerated = 0;
+                let {
+                  result: currentBlockHeight,
+                } = await ctx.coreService.getRpcClient().getBlockCount();
+
+                do {
+                  ({
+                    result: currentBlockHeight,
+                  } = await ctx.coreService.getRpcClient().getBlockCount());
+
+                  await generateBlocks(
+                    ctx.coreService,
+                    blocksToGenerateInOneStep,
+                    NETWORK_LOCAL,
+                    // eslint-disable-next-line no-loop-func
+                    (blocks) => {
+                      blocksGenerated += blocks;
+
+                      observer.next(`${blocksGenerated} blocks generated`);
+                    },
+                  );
+                } while (dip3ActivationHeight > currentBlockHeight);
+
+                observer.complete();
+
+                return this;
+              }),
+            },
+            {
+              title: 'Wait for nodes to have the same height',
+              task: () => waitForNodesToHaveTheSameHeight(
+                ctx.rpcClients,
+                WAIT_FOR_NODES_TIMEOUT,
+              ),
+            },
             {
               title: 'Stopping nodes',
               task: async () => (Promise.all(