diff --git a/dash-docs/protocol-documentation.md b/dash-docs/protocol-documentation.md
index 3f5e82db0111..743a55c37a9f 100644
--- a/dash-docs/protocol-documentation.md
+++ b/dash-docs/protocol-documentation.md
@@ -69,52 +69,6 @@ Bitcoin Public Key https://bitcoin.org/en/glossary/public-key
## Message Types
-### MNANNOUNCE - "mnb"
-
-CMasternodeBroadcast
-
-Whenever a masternode comes online or a client is syncing, they will send this message which describes the masternode entry and how to validate messages from it.
-
-| Field Size | Field Name | Data type | Description |
-| ---------- | ----------- | --------- | ---------- |
-| 36 | outpoint | [COutPoint](#coutpoint) | The unspent output which is holding 1000 DASH
-| # | addr | [CService](#cservice) | IPv4 address of the masternode
-| 33-65 | pubKeyCollateralAddress | [CPubKey](#cpubkey) | CPubKey of the main 1000 DASH unspent output
-| 33-65 | pubKeyMasternode | [CPubKey](#cpubkey) | CPubKey of the secondary signing key (For all other messaging other than announce message)
-| 71-73 | sig | char[] | Signature of this message (verifiable via pubKeyCollateralAddress)
-| 8 | sigTime | int64_t | Time which the signature was created
-| 4 | nProtocolVersion | int | The protocol version of the masternode
-| # | lastPing | [CMasternodePing](#mnping---mnp) | The last known ping of the masternode
-
-### MNPING - "mnp"
-
-CMasternodePing
-
-Every few minutes, masternodes ping the network with a message that propagates the whole network.
-
-| Field Size | Field Name | Data type | Description |
-| ---------- | ----------- | --------- | --------- |
-| 36 | masternodeOutpoint | [COutPoint](#coutpoint) | The unspent output of the masternode which is signing the message
-| 32 | blockHash | uint256 | Current chaintip blockhash minus 12
-| 8 | sigTime | int64_t | Signature time for this ping
-| 71-73 | vchSig | char[] | Signature of this message by masternode (verifiable via pubKeyMasternode)
-| 1 | fSentinelIsCurrent | bool | true if last sentinel ping was current
-| 4 | nSentinelVersion | uint32_t | The version of Sentinel running on the masternode which is signing the message
-| 4 | nDaemonVersion | uint32_t | The version of dashd of the masternode which is signing the message (i.e. CLIENT_VERSION)
-
-### MASTERNODEPAYMENTVOTE - "mnw"
-
-CMasternodePaymentVote
-
-When a new block is found on the network, a masternode quorum will be determined and those 10 selected masternodes will issue a masternode payment vote message to pick the next winning node.
-
-| Field Size | Field Name | Data type | Description |
-| ---------- | ----------- | --------- | ---------- |
-| 36 | masternodeOutpoint | [COutPoint](#coutpoint) | The unspent output of the masternode which is signing the message
-| 4 | nBlockHeight | int | The blockheight which the payee should be paid
-| ? | payeeAddress | CScript | The address to pay to
-| 71-73 | sig | char[] | Signature of the masternode which is signing the message
-
### DSTX - "dstx"
CDarksendBroadcastTx
@@ -265,26 +219,6 @@ Spork
## Undocumented messages
-### MASTERNODEPAYMENTBLOCK - "mnwb"
-
-Masternode Payment Block
-
-*NOTE: Per src/protocol.cpp, there is no message for this (only inventory)*
-
-### MNVERIFY - "mnv"
-
-Masternode Verify
-
-| Field Size | Field Name | Data type | Description |
-| ---------- | ----------- | --------- | ---------- |
-| 36 | masternodeOutpoint1 | [COutPoint](#coutpoint) | The unspent output which is holding 1000 DASH for masternode 1
-| 36 | masternodeOutpoint2 | [COutPoint](#coutpoint) | The unspent output which is holding 1000 DASH for masternode 2
-| # | addr | [CService](#cservice) | IPv4 address / port of the masternode
-| 4 | nonce | int | Nonce
-| 4 | nBlockHeight | int | The blockheight
-| 66* | vchSig1 | char[] | Signature of by masternode 1 (unclear if 66 is the correct size, but this is what it appears to be in most cases)
-| 66* | vchSig2 | char[] | Signature of by masternode 2 (unclear if 66 is the correct size, but this is what it appears to be in most cases)
-
### DSFINALTX - "dsf"
Darksend Final Transaction
@@ -312,16 +246,6 @@ Governance Sync
| 32 | nHash | uint256 | |
| # | filter | CBloomFilter | |
-### DSEG - "dseg"
-
-Masternode List/Entry Sync
-
-Get Masternode list or specific entry
-
-| Field Size | Field Name | Data type | Description |
-| ---------- | ----------- | --------- | ---------- |
-| 36 | masternodeOutpoint | [COutPoint](#coutpoint) | The unspent output which is holding 1000 DASH
-
### SYNCSTATUSCOUNT - "ssc"
Sync Status Count
@@ -335,18 +259,6 @@ Sync Status Count
| Item ID | Name | Description |
| ---------- | ---------- | ----------- |
-| 2 | MASTERNODE_SYNC_LIST | |
-| 3 | MASTERNODE_SYNC_MNW | |
| 4 | MASTERNODE_SYNC_GOVERNANCE | |
| 10 | MASTERNODE_SYNC_GOVOBJ | |
| 11 | MASTERNODE_SYNC_GOVOBJ_VOTE | |
-
-### MASTERNODEPAYMENTSYNC - "mnget"
-
-Masternode Payment Sync
-
-| Field Size | Field Name | Data type | Description |
-| ---------- | ----------- | --------- | ---------- |
-| 4 | nMnCount | int | | (DEPRECATED)
-
-*NOTE: There are no fields in this mesasge starting from protocol 70209*
diff --git a/doc/files.md b/doc/files.md
index ce12114963a7..8326c4e6610e 100644
--- a/doc/files.md
+++ b/doc/files.md
@@ -12,9 +12,7 @@
* fee_estimates.dat: stores statistics used to estimate minimum transaction fees and priorities required for confirmation; since 0.10.0
* mempool.dat: dump of the mempool's transactions; since 0.14.0.
* governance.dat: stores data for governance obgects
-* masternode.conf: contains configuration settings for remote masternodes
* mncache.dat: stores data for masternode list
-* mnpayments.dat: stores data for masternode payments
* netfulfilled.dat: stores data about recently made network requests
* peers.dat: peer IP address database (custom format); since 0.7.0
* wallet.dat: personal wallet (BDB) with keys and transactions
diff --git a/doc/guide-startmany.md b/doc/guide-startmany.md
deleted file mode 100644
index d5aee4a43010..000000000000
--- a/doc/guide-startmany.md
+++ /dev/null
@@ -1,133 +0,0 @@
-# start-many Setup Guide
-
-## Setting up your Wallet
-
-### Create New Wallet Addresses
-
-1. Open the QT Wallet.
-2. Click the Receive tab.
-3. Fill in the form to request a payment.
- * Label: mn01
- * Amount: 1000 (optional)
- * Click *Request payment* button
-5. Click the *Copy Address* button
-
-Create a new wallet address for each Masternode.
-
-Close your QT Wallet.
-
-### Send 1000 DASH to New Addresses
-
-Send exactly 1000 DASH to each new address created above.
-
-### Create New Masternode Private Keys
-
-Open your QT Wallet and go to console (from the menu select `Tools` => `Debug Console`)
-
-Issue the following:
-
-```masternode genkey```
-
-*Note: A masternode private key will need to be created for each Masternode you run. You should not use the same masternode private key for multiple Masternodes.*
-
-Close your QT Wallet.
-
-## Create masternode.conf file
-
-Remember... this is local. Make sure your QT is not running.
-
-Create the `masternode.conf` file in the same directory as your `wallet.dat`.
-
-Copy the masternode private key and correspondig collateral output transaction that holds the 1000 DASH.
-
-*Note: The masternode priviate key is **not** the same as a wallet private key. **Never** put your wallet private key in the masternode.conf file. That is almost equivalent to putting your 1000 DASH on the remote server and defeats the purpose of a hot/cold setup.*
-
-### Get the collateral output
-
-Open your QT Wallet and go to console (from the menu select `Tools` => `Debug Console`)
-
-Issue the following:
-
-```masternode outputs```
-
-Make note of the hash (which is your collateral_output) and index.
-
-### Enter your Masternode details into your masternode.conf file
-[From the dash github repo](https://github.com/dashpay/dash/blob/master/doc/masternode_conf.md)
-
-`masternode.conf` format is a space seperated text file. Each line consisting of an alias, IP address followed by port, masternode private key, collateral output transaction id and collateral output index.
-
-```
-alias ipaddress:port masternode_private_key collateral_output collateral_output_index
-```
-
-Example:
-
-```
-mn01 127.0.0.1:9999 93HaYBVUCYjEMeeH1Y4sBGLALQZE1Yc1K64xiqgX37tGBDQL8Xg 2bcd3c84c84f87eaa86e4e56834c92927a07f9e18718810b92e0d0324456a67c 0
-mn02 127.0.0.2:9999 93WaAb3htPJEV8E9aQcN23Jt97bPex7YvWfgMDTUdWJvzmrMqey aa9f1034d973377a5e733272c3d0eced1de22555ad45d6b24abadff8087948d4 0
-```
-
-## Update dash.conf on server
-
-If you generated a new masternode private key, you will need to update the remote `dash.conf` files.
-
-Shut down the daemon and then edit the file.
-
-```nano .dashcore/dash.conf```
-
-### Edit the masternodeprivkey
-If you generated a new masternode private key, you will need to update the `masternodeprivkey` value in your remote `dash.conf` file.
-
-## Start your Masternodes
-
-### Remote
-
-If your remote server is not running, start your remote daemon as you normally would.
-
-You can confirm that remote server is on the correct block by issuing
-
-```dash-cli getinfo```
-
-and comparing with the official explorer at https://explorer.dash.org/chain/Dash
-
-### Local
-
-Finally... time to start from local.
-
-#### Open up your QT Wallet
-
-From the menu select `Tools` => `Debug Console`
-
-If you want to review your `masternode.conf` setting before starting Masternodes, issue the following in the Debug Console:
-
-```masternode list-conf```
-
-Give it the eye-ball test. If satisfied, you can start your Masternodes one of two ways.
-
-1. `masternode start-alias [alias_from_masternode.conf]`
-Example ```masternode start-alias mn01```
-2. `masternode start-many`
-
-## Verify that Masternodes actually started
-
-### Remote
-
-Issue command `masternode status`
-It should return you something like that:
-```
-dash-cli masternode status
-{
- "outpoint" : "-",
- "service" : ":",
- "pubkey" : "<1000 DASH address>",
- "status" : "Masternode successfully started"
-}
-```
-Command output should have "_Masternode successfully started_" in its `status` field now. If it says "_not capable_" instead, you should check your config again.
-
-### Local
-
-Search your Masternodes on https://dashninja.pl/masternodes.html
-
-_Hint: Bookmark it, you definitely will be using this site a lot._
diff --git a/doc/masternode-budget.md b/doc/masternode-budget.md
index 28feee0079d6..c4cc31daaaa4 100644
--- a/doc/masternode-budget.md
+++ b/doc/masternode-budget.md
@@ -147,7 +147,7 @@ The following RPC commands are supported:
- nextsuperblocksize - Get superblock size for a given blockheight
- projection - Show the projection of which proposals will be paid the next cycle
- vote - Vote on a proposal by single masternode (using dash.conf setup)
- - vote-many - Vote on a proposal by all masternodes (using masternode.conf setup)
+ - vote-many - Vote on a proposal by all masternodes for which the voting key is in the wallet
- vote-alias - Vote on a proposal by alias
- mnfinalbudget "command"... ( "passphrase" )
- vote-many - Vote on a finalized budget
diff --git a/doc/masternode_conf.md b/doc/masternode_conf.md
deleted file mode 100644
index 6e2db264faa4..000000000000
--- a/doc/masternode_conf.md
+++ /dev/null
@@ -1,29 +0,0 @@
-Masternode config
-=======================
-
-Dash Core allows controlling multiple remote masternodes from a single wallet. The wallet needs to have a valid collateral output of 1000 coins for each masternode and uses a configuration file named `masternode.conf` which can be found in the following data directory (depending on your operating system):
- * Windows: %APPDATA%\DashCore\
- * Mac OS: ~/Library/Application Support/DashCore/
- * Unix/Linux: ~/.dashcore/
-
-`masternode.conf` is a space separated text file. Each line consists of an alias, IP address followed by port, masternode private key, collateral output transaction id and collateral output index.
-
-Example:
-```
-mn1 127.0.0.2:19999 93HaYBVUCYjEMeeH1Y4sBGLALQZE1Yc1K64xiqgX37tGBDQL8Xg 7603c20a05258c208b58b0a0d77603b9fc93d47cfa403035f87f3ce0af814566 0
-mn2 127.0.0.4:19999 92Da1aYg6sbenP6uwskJgEY2XWB5LwJ7bXRqc3UPeShtHWJDjDv 5d898e78244f3206e0105f421cdb071d95d111a51cd88eb5511fc0dbf4bfd95f 1
-```
-
-In the example above:
-* the collateral of 1000 DASH for `mn1` is output `0` of transaction [7603c20a05258c208b58b0a0d77603b9fc93d47cfa403035f87f3ce0af814566](https://test.explorer.dash.org/tx/7603c20a05258c208b58b0a0d77603b9fc93d47cfa403035f87f3ce0af814566)
-* the collateral of 1000 DASH for `mn2` is output `1` of transaction [5d898e78244f3206e0105f421cdb071d95d111a51cd88eb5511fc0dbf4bfd95f](https://test.explorer.dash.org/tx/5d898e78244f3206e0105f421cdb071d95d111a51cd88eb5511fc0dbf4bfd95f)
-
-_Note: IPs like 127.0.0.* are not allowed actually, we are using them here for explanatory purposes only. Make sure you have real reachable remote IPs in you `masternode.conf`._
-
-The following RPC commands are available (type `help masternode` in Console for more info):
-* list-conf
-* start-alias \
-* start-all
-* start-missing
-* start-disabled
-* outputs
diff --git a/qa/rpc-tests/autoix-mempool.py b/qa/rpc-tests/autoix-mempool.py
index 9266a06b5101..ab8244c0fdc9 100755
--- a/qa/rpc-tests/autoix-mempool.py
+++ b/qa/rpc-tests/autoix-mempool.py
@@ -118,7 +118,6 @@ def fill_mempool(self):
def run_test(self):
# make sure masternodes are synced
sync_masternodes(self.nodes)
- self.enforce_masternode_payments() # required for bip9 activation
self.activate_autoix_bip9()
self.set_autoix_spork_state(True)
diff --git a/qa/rpc-tests/dip3-deterministicmns.py b/qa/rpc-tests/dip3-deterministicmns.py
index 0ee75ae2d1a1..e4c3381e62ac 100755
--- a/qa/rpc-tests/dip3-deterministicmns.py
+++ b/qa/rpc-tests/dip3-deterministicmns.py
@@ -56,217 +56,82 @@ def run_test(self):
self.nodes[0].generate(1) # generate enough for collaterals
print("controller node has {} dash".format(self.nodes[0].getbalance()))
- # Make sure we're below block 143 (which activates dip3)
+ # Make sure we're below block 432 (which activates dip3)
print("testing rejection of ProTx before dip3 activation")
- assert(self.nodes[0].getblockchaininfo()['blocks'] < 143)
- dip3_deployment = self.nodes[0].getblockchaininfo()['bip9_softforks']['dip0003']
- assert_equal(dip3_deployment['status'], 'defined')
-
- self.test_fail_create_protx(self.nodes[0])
+ assert(self.nodes[0].getblockchaininfo()['blocks'] < 432)
mns = []
- mn_idx = 1
- for i in range(self.num_initial_mn):
- mn = self.create_mn(self.nodes[0], mn_idx, 'mn-%d' % (mn_idx))
- mn_idx += 1
- mns.append(mn)
-
- # mature collaterals
- for i in range(3):
- self.nodes[0].generate(1)
- time.sleep(1)
-
- self.write_mnconf(mns)
-
- self.restart_controller_node()
- for mn in mns:
- self.start_mn(mn)
- self.sync_all()
-
- # force finishing of mnsync
- for node in self.nodes:
- self.force_finish_mnsync(node)
-
- # start MNs
- print("start mns")
- for mn in mns:
- self.start_alias(self.nodes[0], mn.alias)
- print("wait for MNs to appear in MN lists")
- self.wait_for_mnlists(mns, True, False)
-
- print("testing MN payment votes")
- self.test_mn_votes(10)
-
- print("testing instant send")
- self.test_instantsend(10, 5)
-
- print("testing rejection of ProTx before dip3 activation (in states defined, started and locked_in)")
- while self.nodes[0].getblockchaininfo()['bip9_softforks']['dip0003']['status'] == 'defined':
- self.nodes[0].generate(1)
- self.test_fail_create_protx(self.nodes[0])
- while self.nodes[0].getblockchaininfo()['bip9_softforks']['dip0003']['status'] == 'started':
- self.nodes[0].generate(1)
- self.test_fail_create_protx(self.nodes[0])
# prepare mn which should still be accepted later when dip3 activates
print("creating collateral for mn-before-dip3")
- before_dip3_mn = self.create_mn(self.nodes[0], mn_idx, 'mn-before-dip3')
- mn_idx += 1
+ before_dip3_mn = self.prepare_mn(self.nodes[0], 1, 'mn-before-dip3')
+ self.create_mn_collateral(self.nodes[0], before_dip3_mn)
+ mns.append(before_dip3_mn)
- while self.nodes[0].getblockchaininfo()['bip9_softforks']['dip0003']['status'] == 'locked_in':
+ # block 500 starts enforcing DIP3 MN payments
+ while self.nodes[0].getblockcount() < 498:
self.nodes[0].generate(1)
+ print("mining final block for DIP3 activation")
+ self.nodes[0].generate(1)
+
# We have hundreds of blocks to sync here, give it more time
print("syncing blocks for all nodes")
sync_blocks(self.nodes, timeout=120)
# DIP3 has activated here
- print("testing rejection of ProTx right before dip3 activation")
- best_block = self.nodes[0].getbestblockhash()
- self.nodes[0].invalidateblock(best_block)
- self.test_fail_create_protx(self.nodes[0])
- self.nodes[0].reconsiderblock(best_block)
-
- # Now it should be possible to mine ProTx
- self.sync_all()
- self.test_success_create_protx(self.nodes[0])
-
- print("creating collateral for mn-after-dip3")
- after_dip3_mn = self.create_mn(self.nodes[0], mn_idx, 'mn-after-dip3')
- # mature collaterals
- for i in range(3):
- self.nodes[0].generate(1)
- time.sleep(1)
-
- print("testing if we can start a mn which was created before dip3 activation")
- self.write_mnconf(mns + [before_dip3_mn, after_dip3_mn])
- self.restart_controller_node()
- self.force_finish_mnsync(self.nodes[0])
-
- print("start MN %s" % before_dip3_mn.alias)
- mns.append(before_dip3_mn)
+ self.register_mn(self.nodes[0], before_dip3_mn)
self.start_mn(before_dip3_mn)
- self.wait_for_sporks()
- self.force_finish_mnsync_list(before_dip3_mn.node)
- self.start_alias(self.nodes[0], before_dip3_mn.alias)
- self.wait_for_mnlists(mns)
- self.wait_for_mnlists_same()
+ print("registering MNs")
+ for i in range(0, self.num_initial_mn):
+ mn = self.prepare_mn(self.nodes[0], i + 2, "mn-%d" % i)
+ mns.append(mn)
- # Test if nodes still allow creating new non-ProTx MNs now
- print("testing if MN start succeeds when using collateral which was created after dip3 activation")
- print("start MN %s" % after_dip3_mn.alias)
- mns.append(after_dip3_mn)
- self.start_mn(after_dip3_mn)
- self.wait_for_sporks()
- self.force_finish_mnsync_list(after_dip3_mn.node)
- self.start_alias(self.nodes[0], after_dip3_mn.alias)
-
- self.wait_for_mnlists(mns)
- self.wait_for_mnlists_same()
-
- first_upgrade_count = 5
- mns_after_upgrade = []
- mns_to_restart = []
- mns_to_restart_later = []
- mns_protx = []
- print("upgrading first %d MNs to use ProTx (but not deterministic MN lists)" % first_upgrade_count)
- for i in range(first_upgrade_count):
- # let a few of the protx MNs refer to the old collaterals
- fund = (i % 2) == 0
- mns[i] = self.upgrade_mn_protx(mns[i], fund)
- self.nodes[0].generate(1)
+ # start a few MNs before they are registered and a few after they are registered
+ start = (i % 3) == 0
+ if start:
+ self.start_mn(mn)
+ # let a few of the protx MNs refer to the existing collaterals
+ fund = (i % 2) == 0
if fund:
- # collateral has moved, so we need to start it again
- mns_to_restart.append(mns[i])
+ print("register_fund %s" % mn.alias)
+ self.register_fund_mn(self.nodes[0], mn)
else:
- # collateral has not moved, so it should still be in the masternode list even after upgrade
- mns_after_upgrade.append(mns[i])
- mns_to_restart_later.append(mns[i])
- mns_protx.append(mns[i])
- for i in range(first_upgrade_count, len(mns)):
- mns_after_upgrade.append(mns[i])
- self.write_mnconf(mns)
-
- print("wait for freshly funded and upgraded MNs to disappear from MN lists (their collateral was spent)")
- self.wait_for_mnlists(mns_after_upgrade, check=True)
- self.wait_for_mnlists_same()
-
- print("restarting controller and upgraded MNs")
- self.restart_controller_node()
- self.force_finish_mnsync_list(self.nodes[0])
- for mn in mns_to_restart:
- print("restarting MN %s" % mn.alias)
- self.stop_node(mn.idx)
- self.start_mn(mn)
- self.force_finish_mnsync_list(mn.node)
- print('start-alias on upgraded nodes')
- for mn in mns_to_restart:
- self.start_alias(self.nodes[0], mn.alias)
-
- print("wait for upgraded MNs to appear in MN list")
- self.wait_for_mnlists(mns)
- self.wait_for_mnlists_same()
+ print("create_collateral %s" % mn.alias)
+ self.create_mn_collateral(self.nodes[0], mn)
+ print("register %s" % mn.alias)
+ self.register_mn(self.nodes[0], mn)
- print("testing MN payment votes (with mixed ProTx and legacy nodes)")
- self.test_mn_votes(10, test_enforcement=True)
-
- print("testing instant send (with mixed ProTx and legacy nodes)")
- self.test_instantsend(10, 3)
-
- # We still need to restart them as otherwise they won't have the BLS operator key loaded
- print("restart upgraded nodes which refer to old collaterals")
- for mn in mns_to_restart_later:
- print("restarting MN %s" % mn.alias)
- self.stop_node(mn.idx)
- self.start_mn(mn)
- self.force_finish_mnsync_list(mn.node)
-
- print("activating spork15")
- height = self.nodes[0].getblockchaininfo()['blocks']
- spork15_offset = 10
- self.nodes[0].spork('SPORK_15_DETERMINISTIC_MNS_ENABLED', height + spork15_offset)
- self.wait_for_sporks()
-
- print("test that MN list does not change before final spork15 activation")
- for i in range(spork15_offset - 1):
self.nodes[0].generate(1)
- self.sync_all()
- self.wait_for_mnlists(mns)
- self.wait_for_mnlists_same()
-
- print("mining final block which should switch network to deterministic lists")
- self.nodes[0].generate(1)
- self.sync_all()
- ##### WOW...we made it...we are in deterministic MN lists mode now.
- ##### From now on, we don't wait for mnlists to become correct anymore, we always assert that they are correct immediately
+ if not start:
+ self.start_mn(mn)
- print("assert that not upgraded MNs disappeared from MN list")
- self.assert_mnlists(mns_protx)
+ self.sync_all()
+ self.assert_mnlists(mns)
- # enable enforcement and keep it on from now on
- self.nodes[0].spork('SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT', 0)
- self.wait_for_sporks()
+ print("testing instant send")
+ self.test_instantsend(10, 3)
print("test that MNs disappear from the list when the ProTx collateral is spent")
spend_mns_count = 3
- mns_tmp = [] + mns_protx
+ mns_tmp = [] + mns
dummy_txins = []
for i in range(spend_mns_count):
- dummy_txin = self.spend_mn_collateral(mns_protx[i], with_dummy_input_output=True)
+ dummy_txin = self.spend_mn_collateral(mns[i], with_dummy_input_output=True)
dummy_txins.append(dummy_txin)
self.nodes[0].generate(1)
self.sync_all()
- mns_tmp.remove(mns_protx[i])
+ mns_tmp.remove(mns[i])
self.assert_mnlists(mns_tmp)
print("test that reverting the blockchain on a single node results in the mnlist to be reverted as well")
for i in range(spend_mns_count):
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
- mns_tmp.append(mns_protx[spend_mns_count - 1 - i])
+ mns_tmp.append(mns[spend_mns_count - 1 - i])
self.assert_mnlist(self.nodes[0], mns_tmp)
print("cause a reorg with a double spend and check that mnlists are still correct on all nodes")
@@ -275,21 +140,6 @@ def run_test(self):
self.sync_all()
self.assert_mnlists(mns_tmp)
- print("upgrade remaining MNs to ProTx")
- for i in range(first_upgrade_count, len(mns)):
- mns[i] = self.upgrade_mn_protx(mns[i], True)
- mn = mns[i]
- self.nodes[0].generate(1)
- mns_protx.append(mn)
- print("restarting MN %s" % mn.alias)
- self.stop_node(mn.idx)
- self.start_mn(mn)
- self.sync_all()
- self.force_finish_mnsync(mn.node)
- self.assert_mnlists(mns_protx)
-
- self.assert_mnlists(mns_protx)
-
print("test mn payment enforcement with deterministic MNs")
for i in range(20):
node = self.nodes[i % len(self.nodes)]
@@ -297,18 +147,15 @@ def run_test(self):
node.generate(1)
self.sync_all()
- print("testing instant send with deterministic MNs")
- self.test_instantsend(10, 5, timeout=20)
-
print("testing ProUpServTx")
- for mn in mns_protx:
+ for mn in mns:
self.test_protx_update_service(mn)
print("testing P2SH/multisig for payee addresses")
multisig = self.nodes[0].createmultisig(1, [self.nodes[0].getnewaddress(), self.nodes[0].getnewaddress()])['address']
- self.update_mn_payee(mns_protx[0], multisig)
+ self.update_mn_payee(mns[0], multisig)
found_multisig_payee = False
- for i in range(len(mns_protx)):
+ for i in range(len(mns)):
bt = self.nodes[0].getblocktemplate()
expected_payee = bt['masternode'][0]['payee']
expected_amount = bt['masternode'][0]['amount']
@@ -325,24 +172,29 @@ def run_test(self):
print("testing reusing of collaterals for replaced MNs")
for i in range(0, 5):
- mn = mns_protx[i]
+ mn = mns[i]
# a few of these will actually refer to old ProRegTx internal collaterals,
# which should work the same as external collaterals
- mn = self.create_mn_protx(self.nodes[0], mn.idx, 'mn-protx-%d' % mn.idx, mn.collateral_txid, mn.collateral_vout)
- mns_protx[i] = mn
+ new_mn = self.prepare_mn(self.nodes[0], mn.idx, mn.alias)
+ new_mn.collateral_address = mn.collateral_address
+ new_mn.collateral_txid = mn.collateral_txid
+ new_mn.collateral_vout = mn.collateral_vout
+
+ self.register_mn(self.nodes[0], new_mn)
+ mns[i] = new_mn
self.nodes[0].generate(1)
self.sync_all()
- self.assert_mnlists(mns_protx)
- print("restarting MN %s" % mn.alias)
- self.stop_node(mn.idx)
- self.start_mn(mn)
+ self.assert_mnlists(mns)
+ print("restarting MN %s" % new_mn.alias)
+ self.stop_node(new_mn.idx)
+ self.start_mn(new_mn)
self.sync_all()
print("testing instant send with replaced MNs")
self.test_instantsend(10, 3, timeout=20)
print("testing simple PoSe")
- self.assert_mnlists(mns_protx)
+ self.assert_mnlists(mns)
self.nodes[0].spork('SPORK_17_QUORUM_DKG_ENABLED', 0)
self.wait_for_sporks()
@@ -351,9 +203,9 @@ def run_test(self):
if skip_count != 0:
self.nodes[0].generate(skip_count)
- for i in range(len(mns_protx), len(mns_protx) - 2, -1):
- mn = mns_protx[len(mns_protx) - 1]
- mns_protx.remove(mn)
+ for i in range(len(mns), len(mns) - 2, -1):
+ mn = mns[len(mns) - 1]
+ mns.remove(mn)
self.stop_node(mn.idx)
self.nodes.remove(mn.node)
@@ -382,53 +234,40 @@ def run_test(self):
self.sync_all()
assert(punished and banned)
- def create_mn(self, node, idx, alias):
+ def prepare_mn(self, node, idx, alias):
mn = Masternode()
mn.idx = idx
mn.alias = alias
- mn.is_protx = False
+ mn.is_protx = True
mn.p2p_port = p2p_port(mn.idx)
blsKey = node.bls('generate')
- mn.legacyMnkey = node.masternode('genkey')
+ mn.ownerAddr = node.getnewaddress()
+ mn.operatorAddr = blsKey['public']
+ mn.votingAddr = mn.ownerAddr
mn.blsMnkey = blsKey['secret']
+
+ return mn
+
+ def create_mn_collateral(self, node, mn):
mn.collateral_address = node.getnewaddress()
mn.collateral_txid = node.sendtoaddress(mn.collateral_address, 1000)
- rawtx = node.getrawtransaction(mn.collateral_txid, 1)
-
mn.collateral_vout = -1
+ node.generate(1)
+
+ rawtx = node.getrawtransaction(mn.collateral_txid, 1)
for txout in rawtx['vout']:
if txout['value'] == Decimal(1000):
mn.collateral_vout = txout['n']
break
assert(mn.collateral_vout != -1)
- lock = node.lockunspent(False, [{'txid': mn.collateral_txid, 'vout': mn.collateral_vout}])
-
- return mn
-
- def create_mn_protx_base(self, node, idx, alias, legacy_mn_key):
- mn = Masternode()
- mn.idx = idx
- mn.alias = alias
- mn.is_protx = True
- mn.p2p_port = p2p_port(mn.idx)
-
- blsKey = node.bls('generate')
- mn.ownerAddr = node.getnewaddress()
- mn.operatorAddr = blsKey['public']
- mn.votingAddr = mn.ownerAddr
- mn.legacyMnkey = node.masternode('genkey') if legacy_mn_key is None else legacy_mn_key
- mn.blsMnkey = blsKey['secret']
-
- return mn
-
- # create a protx MN and also fund it (using collateral inside ProRegTx)
- def create_mn_protx_fund(self, node, idx, alias, legacy_mn_key=None):
- mn = self.create_mn_protx_base(node, idx, alias, legacy_mn_key=legacy_mn_key)
+ # register a protx MN and also fund it (using collateral inside ProRegTx)
+ def register_fund_mn(self, node, mn):
mn.collateral_address = node.getnewaddress()
+ mn.rewards_address = node.getnewaddress()
- mn.protx_hash = node.protx('register_fund', mn.collateral_address, '127.0.0.1:%d' % mn.p2p_port, mn.ownerAddr, mn.operatorAddr, mn.votingAddr, 0, mn.collateral_address)
+ mn.protx_hash = node.protx('register_fund', mn.collateral_address, '127.0.0.1:%d' % mn.p2p_port, mn.ownerAddr, mn.operatorAddr, mn.votingAddr, 0, mn.rewards_address)
mn.collateral_txid = mn.protx_hash
mn.collateral_vout = -1
@@ -439,23 +278,17 @@ def create_mn_protx_fund(self, node, idx, alias, legacy_mn_key=None):
break
assert(mn.collateral_vout != -1)
- return mn
-
# create a protx MN which refers to an existing collateral
- def create_mn_protx(self, node, idx, alias, collateral_txid, collateral_vout, legacy_mn_key=None):
- mn = self.create_mn_protx_base(node, idx, alias, legacy_mn_key=legacy_mn_key)
+ def register_mn(self, node, mn):
mn.rewards_address = node.getnewaddress()
- mn.protx_hash = node.protx('register', collateral_txid, collateral_vout, '127.0.0.1:%d' % mn.p2p_port, mn.ownerAddr, mn.operatorAddr, mn.votingAddr, 0, mn.rewards_address)
- mn.collateral_txid = collateral_txid
- mn.collateral_vout = collateral_vout
-
- return mn
+ mn.protx_hash = node.protx('register', mn.collateral_txid, mn.collateral_vout, '127.0.0.1:%d' % mn.p2p_port, mn.ownerAddr, mn.operatorAddr, mn.votingAddr, 0, mn.rewards_address)
+ node.generate(1)
def start_mn(self, mn):
while len(self.nodes) <= mn.idx:
self.nodes.append(None)
- extra_args = ['-masternode=1', '-masternodeprivkey=%s' % mn.legacyMnkey, '-masternodeblsprivkey=%s' % mn.blsMnkey]
+ extra_args = ['-masternode=1', '-masternodeblsprivkey=%s' % mn.blsMnkey]
n = start_node(mn.idx, self.options.tmpdir, self.extra_args + extra_args, redirect_stderr=True)
self.nodes[mn.idx] = n
for i in range(0, self.num_nodes):
@@ -463,18 +296,11 @@ def start_mn(self, mn):
connect_nodes_bi(self.nodes, mn.idx, i)
mn.node = self.nodes[mn.idx]
self.sync_all()
+ self.force_finish_mnsync(mn.node)
def spend_mn_collateral(self, mn, with_dummy_input_output=False):
return self.spend_input(mn.collateral_txid, mn.collateral_vout, 1000, with_dummy_input_output)
- def upgrade_mn_protx(self, mn, refund):
- if refund:
- self.spend_mn_collateral(mn)
- mn = self.create_mn_protx_fund(self.nodes[0], mn.idx, 'mn-protx-%d' % mn.idx, legacy_mn_key=mn.legacyMnkey)
- else:
- mn = self.create_mn_protx(self.nodes[0], mn.idx, 'mn-protx-%d' % mn.idx, mn.collateral_txid, mn.collateral_vout, legacy_mn_key=mn.legacyMnkey)
- return mn
-
def update_mn_payee(self, mn, payee):
self.nodes[0].protx('update_registrar', mn.protx_hash, '', '', payee)
self.nodes[0].generate(1)
@@ -515,90 +341,6 @@ def force_finish_mnsync_list(self, node):
return
time.sleep(0.1)
- def write_mnconf_line(self, mn, f):
- conf_line = "%s %s:%d %s %s %d\n" % (mn.alias, '127.0.0.1', mn.p2p_port, mn.legacyMnkey, mn.collateral_txid, mn.collateral_vout)
- f.write(conf_line)
-
- def write_mnconf(self, mns):
- mnconf_file = os.path.join(self.options.tmpdir, "node0/regtest/masternode.conf")
- with open(mnconf_file, 'w') as f:
- for mn in mns:
- self.write_mnconf_line(mn, f)
-
- def start_alias(self, node, alias, should_fail=False):
- # When generating blocks very fast, the logic in miner.cpp:UpdateTime might result in block times ahead of the real time
- # This can easily accumulate to 30 seconds or more, which results in start-alias to fail as it expects the sigTime
- # to be less or equal to the confirmation block time
- # Solution is to sleep in this case.
- lastblocktime = node.getblock(node.getbestblockhash())['time']
- sleeptime = lastblocktime - time.time()
- if sleeptime > 0:
- time.sleep(sleeptime + 1) # +1 to be extra sure
-
- start_result = node.masternode('start-alias', alias)
- if not should_fail:
- assert_equal(start_result, {'result': 'successful', 'alias': alias})
- else:
- assert_equal(start_result, {'result': 'failed', 'alias': alias, 'errorMessage': 'Failed to verify MNB'})
-
- def generate_blocks_until_winners(self, node, count, timeout=60):
- # Winner lists are pretty much messed up when too many blocks were generated in a short time
- # To allow proper testing of winners list, we need to slowly generate a few blocks until the list stabilizes
- good_count = 0
- st = time.time()
- while time.time() < st + timeout:
- height = node.getblockchaininfo()['blocks'] + 10
- winners = node.masternode('winners')
- if str(height) in winners:
- if re.match('[0-9a-zA-Z]*:10', winners[str(height)]):
- good_count += 1
- if good_count >= count:
- return
- else:
- good_count = 0
- node.generate(1)
- self.sync_all()
- time.sleep(1)
- raise AssertionError("generate_blocks_until_winners timed out: {}".format(node.masternode('winners')))
-
- def test_mn_votes(self, block_count, test_enforcement=False):
- self.generate_blocks_until_winners(self.nodes[0], self.num_nodes)
-
- if test_enforcement:
- self.nodes[0].spork('SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT', 0)
- self.wait_for_sporks()
- self.test_invalid_mn_payment(self.nodes[0])
-
- cur_block = 0
- while cur_block < block_count:
- for n1 in self.nodes:
- if cur_block >= block_count:
- break
- if n1 is None:
- continue
-
- if test_enforcement:
- self.test_invalid_mn_payment(n1)
-
- n1.generate(1)
- cur_block += 1
- self.sync_all()
-
- height = n1.getblockchaininfo()['blocks']
- winners = self.wait_for_winners(n1, height + 10)
-
- for n2 in self.nodes:
- if n1 is n2 or n2 is None:
- continue
- winners2 = self.wait_for_winners(n2, height + 10)
- if winners[str(height + 10)] != winners2[str(height + 10)]:
- print("winner1: " + str(winners[str(height + 10)]))
- print("winner2: " + str(winners2[str(height + 10)]))
- raise AssertionError("winners did not match")
-
- if test_enforcement:
- self.nodes[0].spork('SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT', 4070908800)
-
def test_instantsend(self, tx_count, repeat, timeout=20):
self.nodes[0].spork('SPORK_2_INSTANTSEND_ENABLED', 0)
self.wait_for_sporks()
@@ -650,30 +392,6 @@ def wait_for_instant_lock(self, node, node_idx, txid, timeout=10):
time.sleep(0.5)
raise AssertionError("wait_for_instant_lock timed out for: {} on node {}".format(txid, node_idx))
- def wait_for_winners(self, node, height, timeout=5):
- st = time.time()
- while time.time() < st + timeout:
- winners = node.masternode('winners')
- if str(height) in winners:
- if re.match('[0-9a-zA-Z]*:10', winners[str(height)]):
- return winners
- time.sleep(0.5)
- raise AssertionError("wait_for_winners for height {} timed out: {}".format(height, node.masternode('winners')))
-
- def wait_for_mnlists(self, mns, timeout=30, check=False):
- for node in self.nodes:
- self.wait_for_mnlist(node, mns, timeout, check=check)
-
- def wait_for_mnlist(self, node, mns, timeout=30, check=False):
- st = time.time()
- while time.time() < st + timeout:
- if check:
- node.masternode('check')
- if self.compare_mnlist(node, mns):
- return
- time.sleep(0.5)
- raise AssertionError("wait_for_mnlist timed out")
-
def assert_mnlists(self, mns):
for node in self.nodes:
self.assert_mnlist(node, mns)
@@ -715,59 +433,32 @@ def compare_mnlist(self, node, mns):
return False
return True
- def wait_for_mnlists_same(self, timeout=30):
- st = time.time()
- while time.time() < st + timeout:
- mnlist = self.nodes[0].masternode('list', 'status')
- all_match = True
- for node in self.nodes[1:]:
- mnlist2 = node.masternode('list', 'status')
- if mnlist != mnlist2:
- all_match = False
- break
- if all_match:
- return
- time.sleep(0.5)
- raise AssertionError("wait_for_mnlists_same timed out")
-
- def test_fail_create_protx(self, node):
- # Try to create ProTx (should still fail)
- address = node.getnewaddress()
- key = node.getnewaddress()
- blsKey = node.bls('generate')
- assert_raises_jsonrpc(None, "bad-tx-type", node.protx, 'register_fund', address, '127.0.0.1:10000', key, blsKey['public'], key, 0, address)
-
- def test_success_create_protx(self, node):
- address = node.getnewaddress()
- key = node.getnewaddress()
- blsKey = node.bls('generate')
- txid = node.protx('register_fund', address, '127.0.0.1:10000', key, blsKey['public'], key, 0, address)
- rawtx = node.getrawtransaction(txid, 1)
- self.mine_double_spend(node, rawtx['vin'], address, use_mnmerkleroot_from_tip=True)
- self.sync_all()
-
def spend_input(self, txid, vout, amount, with_dummy_input_output=False):
# with_dummy_input_output is useful if you want to test reorgs with double spends of the TX without touching the actual txid/vout
address = self.nodes[0].getnewaddress()
- target = {address: amount}
+
+ txins = [
+ {'txid': txid, 'vout': vout}
+ ]
+ targets = {address: amount}
+
+ dummy_txin = None
if with_dummy_input_output:
dummyaddress = self.nodes[0].getnewaddress()
- target[dummyaddress] = 1
- rawtx = self.nodes[0].createrawtransaction([{'txid': txid, 'vout': vout}], target)
+ unspent = self.nodes[0].listunspent(20)
+ for u in unspent:
+ if u['amount'] > Decimal(1):
+ dummy_txin = {'txid': u['txid'], 'vout': u['vout']}
+ txins.append(dummy_txin)
+ targets[dummyaddress] = float(u['amount'] - Decimal(0.0001))
+ break
+
+ rawtx = self.nodes[0].createrawtransaction(txins, targets)
rawtx = self.nodes[0].fundrawtransaction(rawtx)['hex']
rawtx = self.nodes[0].signrawtransaction(rawtx)['hex']
new_txid = self.nodes[0].sendrawtransaction(rawtx)
- if with_dummy_input_output:
- decoded = self.nodes[0].decoderawtransaction(rawtx)
- for i in range(len(decoded['vout'])):
- # make sure this one can only be spent when explicitely creating a rawtx with these outputs as inputs
- # this ensures that no other TX is chaining on top of this TX
- lock = self.nodes[0].lockunspent(False, [{'txid': new_txid, 'vout': i}])
- for txin in decoded['vin']:
- if txin['txid'] != txid or txin['vout'] != vout:
- return txin
- return None
+ return dummy_txin
def mine_block(self, node, vtx=[], miner_address=None, mn_payee=None, mn_amount=None, use_mnmerkleroot_from_tip=False, expected_error=None):
bt = node.getblocktemplate()
diff --git a/qa/rpc-tests/p2p-autoinstantsend.py b/qa/rpc-tests/p2p-autoinstantsend.py
index 3177515141a2..52f6a75b5f68 100755
--- a/qa/rpc-tests/p2p-autoinstantsend.py
+++ b/qa/rpc-tests/p2p-autoinstantsend.py
@@ -125,7 +125,6 @@ def run_test(self):
set_node_times(self.nodes, get_mocktime())
self.nodes[0].generate(1)
- self.enforce_masternode_payments() # required for bip9 activation
assert(self.get_autoix_bip9_status() == 'defined')
assert(not self.get_autoix_spork_state())
diff --git a/qa/rpc-tests/test_framework/test_framework.py b/qa/rpc-tests/test_framework/test_framework.py
index c209550fcac9..cede7b46a836 100755
--- a/qa/rpc-tests/test_framework/test_framework.py
+++ b/qa/rpc-tests/test_framework/test_framework.py
@@ -309,9 +309,6 @@ def setup_network(self):
for status in mn_info.values():
assert (status == 'ENABLED')
- def enforce_masternode_payments(self):
- self.nodes[0].spork('SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT', 0)
-
def create_raw_trx(self, node_from, node_to, amount, min_inputs, max_inputs):
assert (min_inputs <= max_inputs)
# fill inputs
diff --git a/src/Makefile.am b/src/Makefile.am
index deecee050b92..b84637efd180 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -144,11 +144,10 @@ BITCOIN_CORE_H = \
llmq/quorums_dummydkg.h \
llmq/quorums_utils.h \
llmq/quorums_init.h \
- masternode.h \
+ masternode-meta.h \
masternode-payments.h \
masternode-sync.h \
- masternodeman.h \
- masternodeconfig.h \
+ masternode-utils.h \
memusage.h \
merkleblock.h \
messagesigner.h \
@@ -253,11 +252,10 @@ libdash_server_a_SOURCES = \
llmq/quorums_dummydkg.cpp \
llmq/quorums_utils.cpp \
llmq/quorums_init.cpp \
- masternode.cpp \
+ masternode-meta.cpp \
masternode-payments.cpp \
masternode-sync.cpp \
- masternodeconfig.cpp \
- masternodeman.cpp \
+ masternode-utils.cpp \
merkleblock.cpp \
messagesigner.cpp \
miner.cpp \
diff --git a/src/activemasternode.cpp b/src/activemasternode.cpp
index c488079fcfff..ace2270e6ba0 100644
--- a/src/activemasternode.cpp
+++ b/src/activemasternode.cpp
@@ -6,18 +6,16 @@
#include "evo/deterministicmns.h"
#include "init.h"
#include "masternode-sync.h"
-#include "masternode.h"
-#include "masternodeman.h"
#include "netbase.h"
#include "protocol.h"
+#include "validation.h"
#include "warnings.h"
// Keep track of the active Masternode
CActiveMasternodeInfo activeMasternodeInfo;
-CActiveLegacyMasternodeManager legacyActiveMasternodeManager;
-CActiveDeterministicMasternodeManager* activeMasternodeManager;
+CActiveMasternodeManager* activeMasternodeManager;
-std::string CActiveDeterministicMasternodeManager::GetStateString() const
+std::string CActiveMasternodeManager::GetStateString() const
{
switch (state) {
case MASTERNODE_WAITING_FOR_PROTX:
@@ -37,7 +35,7 @@ std::string CActiveDeterministicMasternodeManager::GetStateString() const
}
}
-std::string CActiveDeterministicMasternodeManager::GetStatus() const
+std::string CActiveMasternodeManager::GetStatus() const
{
switch (state) {
case MASTERNODE_WAITING_FOR_PROTX:
@@ -57,14 +55,12 @@ std::string CActiveDeterministicMasternodeManager::GetStatus() const
}
}
-void CActiveDeterministicMasternodeManager::Init()
+void CActiveMasternodeManager::Init()
{
LOCK(cs_main);
if (!fMasternodeMode) return;
- if (!deterministicMNManager->IsDeterministicMNsSporkActive()) return;
-
if (!GetLocalAddress(activeMasternodeInfo.service)) {
state = MASTERNODE_ERROR;
return;
@@ -89,12 +85,12 @@ void CActiveDeterministicMasternodeManager::Init()
mnListEntry = dmn;
- LogPrintf("CActiveDeterministicMasternodeManager::Init -- proTxHash=%s, proTx=%s\n", mnListEntry->proTxHash.ToString(), mnListEntry->ToString());
+ LogPrintf("CActiveMasternodeManager::Init -- proTxHash=%s, proTx=%s\n", mnListEntry->proTxHash.ToString(), mnListEntry->ToString());
if (activeMasternodeInfo.service != mnListEntry->pdmnState->addr) {
state = MASTERNODE_ERROR;
strError = "Local address does not match the address from ProTx";
- LogPrintf("CActiveDeterministicMasternodeManager::Init -- ERROR: %s", strError);
+ LogPrintf("CActiveMasternodeManager::Init -- ERROR: %s", strError);
return;
}
@@ -103,13 +99,13 @@ void CActiveDeterministicMasternodeManager::Init()
state = MASTERNODE_READY;
}
-void CActiveDeterministicMasternodeManager::UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork, bool fInitialDownload)
+void CActiveMasternodeManager::UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork, bool fInitialDownload)
{
LOCK(cs_main);
if (!fMasternodeMode) return;
- if (!deterministicMNManager->IsDeterministicMNsSporkActive(pindexNew->nHeight)) return;
+ if (!deterministicMNManager->IsDIP3Active(pindexNew->nHeight)) return;
if (state == MASTERNODE_WAITING_FOR_PROTX) {
Init();
@@ -136,10 +132,10 @@ void CActiveDeterministicMasternodeManager::UpdatedBlockTip(const CBlockIndex* p
}
}
-bool CActiveDeterministicMasternodeManager::GetLocalAddress(CService& addrRet)
+bool CActiveMasternodeManager::GetLocalAddress(CService& addrRet)
{
// First try to find whatever local address is specified by externalip option
- bool fFoundLocal = GetLocal(addrRet) && CMasternode::IsValidNetAddr(addrRet);
+ bool fFoundLocal = GetLocal(addrRet) && IsValidNetAddr(addrRet);
if (!fFoundLocal && Params().NetworkIDString() == CBaseChainParams::REGTEST) {
if (Lookup("127.0.0.1", addrRet, GetListenPort(), false)) {
fFoundLocal = true;
@@ -147,281 +143,16 @@ bool CActiveDeterministicMasternodeManager::GetLocalAddress(CService& addrRet)
}
if (!fFoundLocal) {
strError = "Can't detect valid external address. Please consider using the externalip configuration option if problem persists. Make sure to use IPv4 address only.";
- LogPrintf("CActiveDeterministicMasternodeManager::GetLocalAddress -- ERROR: %s\n", strError);
+ LogPrintf("CActiveMasternodeManager::GetLocalAddress -- ERROR: %s\n", strError);
return false;
}
return true;
}
-/********* LEGACY *********/
-
-void CActiveLegacyMasternodeManager::ManageState(CConnman& connman)
-{
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) return;
-
- LogPrint("masternode", "CActiveLegacyMasternodeManager::ManageState -- Start\n");
- if (!fMasternodeMode) {
- LogPrint("masternode", "CActiveLegacyMasternodeManager::ManageState -- Not a masternode, returning\n");
- return;
- }
- if (Params().NetworkIDString() != CBaseChainParams::REGTEST && !masternodeSync.IsBlockchainSynced()) {
- nState = ACTIVE_MASTERNODE_SYNC_IN_PROCESS;
- LogPrintf("CActiveLegacyMasternodeManager::ManageState -- %s: %s\n", GetStateString(), GetStatus());
- return;
- }
-
- if (nState == ACTIVE_MASTERNODE_SYNC_IN_PROCESS) {
- nState = ACTIVE_MASTERNODE_INITIAL;
- }
-
- LogPrint("masternode", "CActiveLegacyMasternodeManager::ManageState -- status = %s, type = %s, pinger enabled = %d\n", GetStatus(), GetTypeString(), fPingerEnabled);
-
- if (eType == MASTERNODE_UNKNOWN) {
- ManageStateInitial(connman);
- }
-
- if (eType == MASTERNODE_REMOTE) {
- ManageStateRemote();
- }
-
- SendMasternodePing(connman);
-}
-
-std::string CActiveLegacyMasternodeManager::GetStateString() const
+bool CActiveMasternodeManager::IsValidNetAddr(CService addrIn)
{
- switch (nState) {
- case ACTIVE_MASTERNODE_INITIAL:
- return "INITIAL";
- case ACTIVE_MASTERNODE_SYNC_IN_PROCESS:
- return "SYNC_IN_PROCESS";
- case ACTIVE_MASTERNODE_INPUT_TOO_NEW:
- return "INPUT_TOO_NEW";
- case ACTIVE_MASTERNODE_NOT_CAPABLE:
- return "NOT_CAPABLE";
- case ACTIVE_MASTERNODE_STARTED:
- return "STARTED";
- default:
- return "UNKNOWN";
- }
-}
-
-std::string CActiveLegacyMasternodeManager::GetStatus() const
-{
- switch (nState) {
- case ACTIVE_MASTERNODE_INITIAL:
- return "Node just started, not yet activated";
- case ACTIVE_MASTERNODE_SYNC_IN_PROCESS:
- return "Sync in progress. Must wait until sync is complete to start Masternode";
- case ACTIVE_MASTERNODE_INPUT_TOO_NEW:
- return strprintf("Masternode input must have at least %d confirmations", Params().GetConsensus().nMasternodeMinimumConfirmations);
- case ACTIVE_MASTERNODE_NOT_CAPABLE:
- return "Not capable masternode: " + strNotCapableReason;
- case ACTIVE_MASTERNODE_STARTED:
- return "Masternode successfully started";
- default:
- return "Unknown";
- }
-}
-
-std::string CActiveLegacyMasternodeManager::GetTypeString() const
-{
- std::string strType;
- switch (eType) {
- case MASTERNODE_REMOTE:
- strType = "REMOTE";
- break;
- default:
- strType = "UNKNOWN";
- break;
- }
- return strType;
-}
-
-bool CActiveLegacyMasternodeManager::SendMasternodePing(CConnman& connman)
-{
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) return false;
-
- if (!fPingerEnabled) {
- LogPrint("masternode", "CActiveLegacyMasternodeManager::SendMasternodePing -- %s: masternode ping service is disabled, skipping...\n", GetStateString());
- return false;
- }
-
- if (!mnodeman.Has(activeMasternodeInfo.outpoint)) {
- strNotCapableReason = "Masternode not in masternode list";
- nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
- LogPrintf("CActiveLegacyMasternodeManager::SendMasternodePing -- %s: %s\n", GetStateString(), strNotCapableReason);
- return false;
- }
-
- CMasternodePing mnp(activeMasternodeInfo.outpoint);
- mnp.nSentinelVersion = nSentinelVersion;
- mnp.fSentinelIsCurrent =
- (abs(GetAdjustedTime() - nSentinelPingTime) < MASTERNODE_SENTINEL_PING_MAX_SECONDS);
- if (!mnp.Sign(activeMasternodeInfo.legacyKeyOperator, activeMasternodeInfo.legacyKeyIDOperator)) {
- LogPrintf("CActiveLegacyMasternodeManager::SendMasternodePing -- ERROR: Couldn't sign Masternode Ping\n");
- return false;
- }
-
- // Update lastPing for our masternode in Masternode list
- if (mnodeman.IsMasternodePingedWithin(activeMasternodeInfo.outpoint, MASTERNODE_MIN_MNP_SECONDS, mnp.sigTime)) {
- LogPrintf("CActiveLegacyMasternodeManager::SendMasternodePing -- Too early to send Masternode Ping\n");
- return false;
- }
-
- mnodeman.SetMasternodeLastPing(activeMasternodeInfo.outpoint, mnp);
-
- LogPrintf("CActiveLegacyMasternodeManager::SendMasternodePing -- Relaying ping, collateral=%s\n", activeMasternodeInfo.outpoint.ToStringShort());
- mnp.Relay(connman);
-
- return true;
-}
-
-bool CActiveLegacyMasternodeManager::UpdateSentinelPing(int version)
-{
- nSentinelVersion = version;
- nSentinelPingTime = GetAdjustedTime();
-
- return true;
-}
-
-void CActiveLegacyMasternodeManager::DoMaintenance(CConnman& connman)
-{
- if (ShutdownRequested()) return;
-
- ManageState(connman);
-}
-
-void CActiveLegacyMasternodeManager::ManageStateInitial(CConnman& connman)
-{
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) return;
-
- LogPrint("masternode", "CActiveLegacyMasternodeManager::ManageStateInitial -- status = %s, type = %s, pinger enabled = %d\n", GetStatus(), GetTypeString(), fPingerEnabled);
-
- // Check that our local network configuration is correct
- if (!fListen) {
- // listen option is probably overwritten by smth else, no good
- nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
- strNotCapableReason = "Masternode must accept connections from outside. Make sure listen configuration option is not overwritten by some another parameter.";
- LogPrintf("CActiveLegacyMasternodeManager::ManageStateInitial -- %s: %s\n", GetStateString(), strNotCapableReason);
- return;
- }
-
- // First try to find whatever local address is specified by externalip option
- bool fFoundLocal = GetLocal(activeMasternodeInfo.service) && CMasternode::IsValidNetAddr(activeMasternodeInfo.service);
- if (!fFoundLocal) {
- bool empty = true;
- // If we have some peers, let's try to find our local address from one of them
- connman.ForEachNodeContinueIf(CConnman::AllNodes, [&fFoundLocal, &empty](CNode* pnode) {
- empty = false;
- if (pnode->addr.IsIPv4())
- fFoundLocal = GetLocal(activeMasternodeInfo.service, &pnode->addr) && CMasternode::IsValidNetAddr(activeMasternodeInfo.service);
- return !fFoundLocal;
- });
- // nothing and no live connections, can't do anything for now
- if (empty) {
- nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
- strNotCapableReason = "Can't detect valid external address. Will retry when there are some connections available.";
- LogPrintf("CActiveLegacyMasternodeManager::ManageStateInitial -- %s: %s\n", GetStateString(), strNotCapableReason);
- return;
- }
- }
-
- if (!fFoundLocal && Params().NetworkIDString() == CBaseChainParams::REGTEST) {
- if (Lookup("127.0.0.1", activeMasternodeInfo.service, GetListenPort(), false)) {
- fFoundLocal = true;
- }
- }
-
- if (!fFoundLocal) {
- nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
- strNotCapableReason = "Can't detect valid external address. Please consider using the externalip configuration option if problem persists. Make sure to use IPv4 address only.";
- LogPrintf("CActiveLegacyMasternodeManager::ManageStateInitial -- %s: %s\n", GetStateString(), strNotCapableReason);
- return;
- }
-
- int mainnetDefaultPort = Params(CBaseChainParams::MAIN).GetDefaultPort();
- if (Params().NetworkIDString() == CBaseChainParams::MAIN) {
- if (activeMasternodeInfo.service.GetPort() != mainnetDefaultPort) {
- nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
- strNotCapableReason = strprintf("Invalid port: %u - only %d is supported on mainnet.", activeMasternodeInfo.service.GetPort(), mainnetDefaultPort);
- LogPrintf("CActiveLegacyMasternodeManager::ManageStateInitial -- %s: %s\n", GetStateString(), strNotCapableReason);
- return;
- }
- } else if (activeMasternodeInfo.service.GetPort() == mainnetDefaultPort) {
- nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
- strNotCapableReason = strprintf("Invalid port: %u - %d is only supported on mainnet.", activeMasternodeInfo.service.GetPort(), mainnetDefaultPort);
- LogPrintf("CActiveLegacyMasternodeManager::ManageStateInitial -- %s: %s\n", GetStateString(), strNotCapableReason);
- return;
- }
-
- if (Params().NetworkIDString() != CBaseChainParams::REGTEST) {
- // Check socket connectivity
- LogPrintf("CActiveLegacyMasternodeManager::ManageStateInitial -- Checking inbound connection to '%s'\n", activeMasternodeInfo.service.ToString());
- SOCKET hSocket;
- bool fConnected = ConnectSocket(activeMasternodeInfo.service, hSocket, nConnectTimeout) && IsSelectableSocket(hSocket);
- CloseSocket(hSocket);
-
- if (!fConnected) {
- nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
- strNotCapableReason = "Could not connect to " + activeMasternodeInfo.service.ToString();
- LogPrintf("CActiveLegacyMasternodeManager::ManageStateInitial -- %s: %s\n", GetStateString(), strNotCapableReason);
- return;
- }
- }
- // Default to REMOTE
- eType = MASTERNODE_REMOTE;
-
- LogPrint("masternode", "CActiveLegacyMasternodeManager::ManageStateInitial -- End status = %s, type = %s, pinger enabled = %d\n", GetStatus(), GetTypeString(), fPingerEnabled);
-}
-
-void CActiveLegacyMasternodeManager::ManageStateRemote()
-{
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) return;
-
- LogPrint("masternode", "CActiveLegacyMasternodeManager::ManageStateRemote -- Start status = %s, type = %s, pinger enabled = %d, keyIDOperator = %s\n",
- GetStatus(), GetTypeString(), fPingerEnabled, activeMasternodeInfo.legacyKeyIDOperator.ToString());
-
- mnodeman.CheckMasternode(activeMasternodeInfo.legacyKeyIDOperator, true);
- masternode_info_t infoMn;
- if (mnodeman.GetMasternodeInfo(activeMasternodeInfo.legacyKeyIDOperator, infoMn)) {
- if (infoMn.nProtocolVersion != PROTOCOL_VERSION) {
- nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
- strNotCapableReason = "Invalid protocol version";
- LogPrintf("CActiveLegacyMasternodeManager::ManageStateRemote -- %s: %s\n", GetStateString(), strNotCapableReason);
- return;
- }
- if (activeMasternodeInfo.service != infoMn.addr) {
- nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
- strNotCapableReason = "Broadcasted IP doesn't match our external address. Make sure you issued a new broadcast if IP of this masternode changed recently.";
- LogPrintf("CActiveLegacyMasternodeManager::ManageStateRemote -- %s: %s\n", GetStateString(), strNotCapableReason);
- return;
- }
- if (!CMasternode::IsValidStateForAutoStart(infoMn.nActiveState)) {
- nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
- strNotCapableReason = strprintf("Masternode in %s state", CMasternode::StateToString(infoMn.nActiveState));
- LogPrintf("CActiveLegacyMasternodeManager::ManageStateRemote -- %s: %s\n", GetStateString(), strNotCapableReason);
- return;
- }
- auto dmn = deterministicMNManager->GetListAtChainTip().GetMNByCollateral(infoMn.outpoint);
- if (dmn) {
- if (dmn->pdmnState->addr != infoMn.addr) {
- nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
- strNotCapableReason = strprintf("Masternode collateral is a ProTx and ProTx address does not match local address");
- LogPrintf("CActiveLegacyMasternodeManager::ManageStateRemote -- %s: %s\n", GetStateString(), strNotCapableReason);
- return;
- }
- LogPrintf("CActiveLegacyMasternodeManager::ManageStateRemote -- Collateral is a ProTx\n");
- }
- if (nState != ACTIVE_MASTERNODE_STARTED) {
- LogPrintf("CActiveLegacyMasternodeManager::ManageStateRemote -- STARTED!\n");
- activeMasternodeInfo.outpoint = infoMn.outpoint;
- activeMasternodeInfo.service = infoMn.addr;
- fPingerEnabled = true;
- nState = ACTIVE_MASTERNODE_STARTED;
- }
- } else {
- nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
- strNotCapableReason = "Masternode not in masternode list";
- LogPrintf("CActiveLegacyMasternodeManager::ManageStateRemote -- %s: %s\n", GetStateString(), strNotCapableReason);
- }
+ // TODO: regtest is fine with any addresses for now,
+ // should probably be a bit smarter if one day we start to implement tests for this
+ return Params().NetworkIDString() == CBaseChainParams::REGTEST ||
+ (addrIn.IsIPv4() && IsReachable(addrIn) && addrIn.IsRoutable());
}
diff --git a/src/activemasternode.h b/src/activemasternode.h
index e83b4edba7b3..f7a4dba0355e 100644
--- a/src/activemasternode.h
+++ b/src/activemasternode.h
@@ -15,8 +15,7 @@
#include "evo/providertx.h"
struct CActiveMasternodeInfo;
-class CActiveLegacyMasternodeManager;
-class CActiveDeterministicMasternodeManager;
+class CActiveMasternodeManager;
static const int ACTIVE_MASTERNODE_INITIAL = 0; // initial state
static const int ACTIVE_MASTERNODE_SYNC_IN_PROCESS = 1;
@@ -25,14 +24,10 @@ static const int ACTIVE_MASTERNODE_NOT_CAPABLE = 3;
static const int ACTIVE_MASTERNODE_STARTED = 4;
extern CActiveMasternodeInfo activeMasternodeInfo;
-extern CActiveLegacyMasternodeManager legacyActiveMasternodeManager;
-extern CActiveDeterministicMasternodeManager* activeMasternodeManager;
+extern CActiveMasternodeManager* activeMasternodeManager;
struct CActiveMasternodeInfo {
// Keys for the active Masternode
- CKeyID legacyKeyIDOperator;
- CKey legacyKeyOperator;
-
std::unique_ptr blsPubKeyOperator;
std::unique_ptr blsKeyOperator;
@@ -43,7 +38,7 @@ struct CActiveMasternodeInfo {
};
-class CActiveDeterministicMasternodeManager : public CValidationInterface
+class CActiveMasternodeManager : public CValidationInterface
{
public:
enum masternode_state_t {
@@ -70,60 +65,10 @@ class CActiveDeterministicMasternodeManager : public CValidationInterface
std::string GetStateString() const;
std::string GetStatus() const;
-private:
- bool GetLocalAddress(CService& addrRet);
-};
-
-// Responsible for activating the Masternode and pinging the network (legacy MN list)
-class CActiveLegacyMasternodeManager
-{
-public:
- enum masternode_type_enum_t {
- MASTERNODE_UNKNOWN = 0,
- MASTERNODE_REMOTE = 1
- };
+ static bool IsValidNetAddr(CService addrIn);
private:
- // critical section to protect the inner data structures
- mutable CCriticalSection cs;
-
- masternode_type_enum_t eType;
-
- bool fPingerEnabled;
-
- /// Ping Masternode
- bool SendMasternodePing(CConnman& connman);
-
- // sentinel ping data
- int64_t nSentinelPingTime;
- uint32_t nSentinelVersion;
-
-public:
- int nState; // should be one of ACTIVE_MASTERNODE_XXXX
- std::string strNotCapableReason;
-
-
- CActiveLegacyMasternodeManager() :
- eType(MASTERNODE_UNKNOWN),
- fPingerEnabled(false),
- nState(ACTIVE_MASTERNODE_INITIAL)
- {
- }
-
- /// Manage state of active Masternode
- void ManageState(CConnman& connman);
-
- std::string GetStateString() const;
- std::string GetStatus() const;
- std::string GetTypeString() const;
-
- bool UpdateSentinelPing(int version);
-
- void DoMaintenance(CConnman& connman);
-
-private:
- void ManageStateInitial(CConnman& connman);
- void ManageStateRemote();
+ bool GetLocalAddress(CService& addrRet);
};
#endif
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index ad695bc62d36..d3c517c2254c 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -197,6 +197,8 @@ class CMainParams : public CChainParams {
consensus.BIP65Height = 619382; // 00000000000076d8fcea02ec0963de4abfd01e771fec0863f960c2c64fe6f357
consensus.BIP66Height = 245817; // 00000000000b1fa2dfa312863570e13fae9ca7b5566cb27e55422620b469aefa
consensus.DIP0001Height = 782208;
+ consensus.DIP0003Height = 1000000000; // TODO update after DIP3 is deployed
+ consensus.DIP0003Hash = uint256(); // TODO update after DIP3 is deployed
consensus.powLimit = uint256S("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // ~uint256(0) >> 20
consensus.nPowTargetTimespan = 24 * 60 * 60; // Dash: 1 day
consensus.nPowTargetSpacing = 2.5 * 60; // Dash: 2.5 minutes
@@ -359,6 +361,8 @@ class CTestNetParams : public CChainParams {
consensus.BIP65Height = 2431; // 0000039cf01242c7f921dcb4806a5994bc003b48c1973ae0c89b67809c2bb2ab
consensus.BIP66Height = 2075; // 0000002acdd29a14583540cb72e1c5cc83783560e38fa7081495d474fe1671f7
consensus.DIP0001Height = 5500;
+ consensus.DIP0003Height = 1000000000; // TODO update after DIP3 is deployed
+ consensus.DIP0003Hash = uint256(); // TODO update after DIP3 is deployed
consensus.powLimit = uint256S("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // ~uint256(0) >> 20
consensus.nPowTargetTimespan = 24 * 60 * 60; // Dash: 1 day
consensus.nPowTargetSpacing = 2.5 * 60; // Dash: 2.5 minutes
@@ -504,6 +508,8 @@ class CDevNetParams : public CChainParams {
consensus.BIP65Height = 1; // BIP65 activated immediately on devnet
consensus.BIP66Height = 1; // BIP66 activated immediately on devnet
consensus.DIP0001Height = 2; // DIP0001 activated immediately on devnet
+ consensus.DIP0003Height = 2; // DIP0003 activated immediately on devnet
+ consensus.DIP0003Hash = uint256();
consensus.powLimit = uint256S("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // ~uint256(0) >> 1
consensus.nPowTargetTimespan = 24 * 60 * 60; // Dash: 1 day
consensus.nPowTargetSpacing = 2.5 * 60; // Dash: 2.5 minutes
@@ -653,7 +659,9 @@ class CRegTestParams : public CChainParams {
consensus.BIP34Hash = uint256();
consensus.BIP65Height = 1351; // BIP65 activated on regtest (Used in rpc activation tests)
consensus.BIP66Height = 1251; // BIP66 activated on regtest (Used in rpc activation tests)
- consensus.DIP0001Height = 2000;
+ consensus.DIP0001Height = 500;
+ consensus.DIP0003Height = 500;
+ consensus.DIP0003Hash = uint256();
consensus.powLimit = uint256S("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // ~uint256(0) >> 1
consensus.nPowTargetTimespan = 24 * 60 * 60; // Dash: 1 day
consensus.nPowTargetSpacing = 2.5 * 60; // Dash: 2.5 minutes
diff --git a/src/consensus/params.h b/src/consensus/params.h
index c6dc9d5f40e8..aeca8e519207 100644
--- a/src/consensus/params.h
+++ b/src/consensus/params.h
@@ -129,6 +129,9 @@ struct Params {
int BIP66Height;
/** Block height at which DIP0001 becomes active */
int DIP0001Height;
+ /** Block height at which DIP0003 becomes active */
+ int DIP0003Height;
+ uint256 DIP0003Hash;
/**
* Minimum blocks including miner confirmation of the total of nMinerConfirmationWindow blocks in a retargeting period,
* (nPowTargetTimespan / nPowTargetSpacing) which is also used for BIP9 deployments.
diff --git a/src/dashd.cpp b/src/dashd.cpp
index 03e67d725c6a..af1b1cdc0e4a 100644
--- a/src/dashd.cpp
+++ b/src/dashd.cpp
@@ -16,7 +16,6 @@
#include "noui.h"
#include "scheduler.h"
#include "util.h"
-#include "masternodeconfig.h"
#include "httpserver.h"
#include "httprpc.h"
#include "utilstrencodings.h"
@@ -125,13 +124,6 @@ bool AppInit(int argc, char* argv[])
return false;
}
- // parse masternode.conf
- std::string strErr;
- if(!masternodeConfig.read(strErr)) {
- fprintf(stderr,"Error reading masternode configuration file: %s\n", strErr.c_str());
- return false;
- }
-
// Command-line RPC
bool fCommandLine = false;
for (int i = 1; i < argc; i++)
diff --git a/src/dsnotificationinterface.cpp b/src/dsnotificationinterface.cpp
index 625641d01110..9be6c84d39bd 100644
--- a/src/dsnotificationinterface.cpp
+++ b/src/dsnotificationinterface.cpp
@@ -6,13 +6,13 @@
#include "dsnotificationinterface.h"
#include "instantx.h"
#include "governance.h"
-#include "masternodeman.h"
#include "masternode-payments.h"
#include "masternode-sync.h"
#include "privatesend.h"
#ifdef ENABLE_WALLET
#include "privatesend-client.h"
#endif // ENABLE_WALLET
+#include "validation.h"
#include "evo/deterministicmns.h"
@@ -56,13 +56,11 @@ void CDSNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, con
if (fLiteMode)
return;
- mnodeman.UpdatedBlockTip(pindexNew);
CPrivateSend::UpdatedBlockTip(pindexNew);
#ifdef ENABLE_WALLET
privateSendClient.UpdatedBlockTip(pindexNew);
#endif // ENABLE_WALLET
instantsend.UpdatedBlockTip(pindexNew);
- mnpayments.UpdatedBlockTip(pindexNew, connman);
governance.UpdatedBlockTip(pindexNew, connman);
}
@@ -71,3 +69,10 @@ void CDSNotificationInterface::SyncTransaction(const CTransaction &tx, const CBl
instantsend.SyncTransaction(tx, pindex, posInBlock);
CPrivateSend::SyncTransaction(tx, pindex, posInBlock);
}
+
+void CDSNotificationInterface::NotifyMasternodeListChanged(const CDeterministicMNList& newList)
+{
+ governance.CheckMasternodeOrphanObjects(connman);
+ governance.CheckMasternodeOrphanVotes(connman);
+ governance.UpdateCachesAndClean();
+}
diff --git a/src/dsnotificationinterface.h b/src/dsnotificationinterface.h
index 8e7df34a3309..b3611ae1b2da 100644
--- a/src/dsnotificationinterface.h
+++ b/src/dsnotificationinterface.h
@@ -22,6 +22,7 @@ class CDSNotificationInterface : public CValidationInterface
void NotifyHeaderTip(const CBlockIndex *pindexNew, bool fInitialDownload) override;
void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) override;
void SyncTransaction(const CTransaction &tx, const CBlockIndex *pindex, int posInBlock) override;
+ void NotifyMasternodeListChanged(const CDeterministicMNList& newList);
private:
CConnman& connman;
diff --git a/src/evo/deterministicmns.cpp b/src/evo/deterministicmns.cpp
index 8dc45bec4272..98890ce6a840 100644
--- a/src/evo/deterministicmns.cpp
+++ b/src/evo/deterministicmns.cpp
@@ -9,7 +9,6 @@
#include "chainparams.h"
#include "core_io.h"
#include "script/standard.h"
-#include "spork.h"
#include "validation.h"
#include "validationinterface.h"
@@ -150,6 +149,15 @@ CDeterministicMNCPtr CDeterministicMNList::GetMNByCollateral(const COutPoint& co
return GetUniquePropertyMN(collateralOutpoint);
}
+CDeterministicMNCPtr CDeterministicMNList::GetValidMNByCollateral(const COutPoint& collateralOutpoint) const
+{
+ auto dmn = GetMNByCollateral(collateralOutpoint);
+ if (dmn && !IsMNValid(dmn)) {
+ return nullptr;
+ }
+ return dmn;
+}
+
static int CompareByLastPaid_GetHeight(const CDeterministicMN& dmn)
{
int height = dmn.pdmnState->nLastPaidHeight;
@@ -463,8 +471,18 @@ bool CDeterministicMNManager::ProcessBlock(const CBlock& block, const CBlockInde
__func__, nHeight, newList.GetAllMNsCount());
}
- if (nHeight == GetSpork15Value()) {
- LogPrintf("CDeterministicMNManager::%s -- spork15 is active now. nHeight=%d\n", __func__, nHeight);
+ if (!diff.addedMNs.empty() || !diff.removedMns.empty()) {
+ GetMainSignals().NotifyMasternodeListChanged(newList);
+ }
+
+ const auto& consensusParams = Params().GetConsensus();
+ if (nHeight == consensusParams.DIP0003Height) {
+ if (!consensusParams.DIP0003Hash.IsNull() && consensusParams.DIP0003Hash != pindex->GetBlockHash()) {
+ LogPrintf("CDeterministicMNManager::%s -- DIP3 activation block has wrong hash: hash=%s, expected=%s, nHeight=%d\n", __func__,
+ pindex->GetBlockHash().ToString(), consensusParams.DIP0003Hash.ToString(), nHeight);
+ return _state.DoS(100, false, REJECT_INVALID, "bad-dip3-block");
+ }
+ LogPrintf("CDeterministicMNManager::%s -- DIP3 is active now. nHeight=%d\n", __func__, nHeight);
}
CleanupCache(nHeight);
@@ -479,12 +497,21 @@ bool CDeterministicMNManager::UndoBlock(const CBlock& block, const CBlockIndex*
int nHeight = pindex->nHeight;
uint256 blockHash = block.GetHash();
+ CDeterministicMNListDiff diff;
+ evoDb.Read(std::make_pair(DB_LIST_DIFF, blockHash), diff);
+
evoDb.Erase(std::make_pair(DB_LIST_DIFF, blockHash));
evoDb.Erase(std::make_pair(DB_LIST_SNAPSHOT, blockHash));
mnListsCache.erase(blockHash);
- if (nHeight == GetSpork15Value()) {
- LogPrintf("CDeterministicMNManager::%s -- spork15 is not active anymore. nHeight=%d\n", __func__, nHeight);
+ if (!diff.addedMNs.empty() || !diff.removedMns.empty()) {
+ auto prevList = GetListForBlock(pindex->pprev->GetBlockHash());
+ GetMainSignals().NotifyMasternodeListChanged(prevList);
+ }
+
+ const auto& consensusParams = Params().GetConsensus();
+ if (nHeight == consensusParams.DIP0003Height) {
+ LogPrintf("CDeterministicMNManager::%s -- DIP3 is not active anymore. nHeight=%d\n", __func__, nHeight);
}
return true;
@@ -818,25 +845,6 @@ CDeterministicMNList CDeterministicMNManager::GetListAtChainTip()
return GetListForBlock(tipBlockHash);
}
-bool CDeterministicMNManager::HasValidMNCollateralAtChainTip(const COutPoint& outpoint)
-{
- auto mnList = GetListAtChainTip();
- auto dmn = mnList.GetMNByCollateral(outpoint);
- return dmn && mnList.IsMNValid(dmn);
-}
-
-bool CDeterministicMNManager::HasMNCollateralAtChainTip(const COutPoint& outpoint)
-{
- auto mnList = GetListAtChainTip();
- auto dmn = mnList.GetMNByCollateral(outpoint);
- return dmn != nullptr;
-}
-
-int64_t CDeterministicMNManager::GetSpork15Value()
-{
- return sporkManager.GetSporkValue(SPORK_15_DETERMINISTIC_MNS_ENABLED);
-}
-
bool CDeterministicMNManager::IsProTxWithCollateral(const CTransactionRef& tx, uint32_t n)
{
if (tx->nVersion != 3 || tx->nType != TRANSACTION_PROVIDER_REGISTER) {
@@ -859,16 +867,11 @@ bool CDeterministicMNManager::IsProTxWithCollateral(const CTransactionRef& tx, u
return true;
}
-bool CDeterministicMNManager::IsDeterministicMNsSporkActive(int nHeight)
+bool CDeterministicMNManager::IsDIP3Active(int nHeight)
{
LOCK(cs);
-
- if (nHeight == -1) {
- nHeight = tipHeight;
- }
-
- int64_t spork15Value = GetSpork15Value();
- return nHeight >= spork15Value;
+ assert(nHeight >= 0);
+ return nHeight >= Params().GetConsensus().DIP0003Height;
}
void CDeterministicMNManager::CleanupCache(int nHeight)
diff --git a/src/evo/deterministicmns.h b/src/evo/deterministicmns.h
index ba0d1fa8541c..fadd247623a9 100644
--- a/src/evo/deterministicmns.h
+++ b/src/evo/deterministicmns.h
@@ -289,10 +289,23 @@ class CDeterministicMNList
{
return GetMN(proTxHash) != nullptr;
}
+ bool HasValidMN(const uint256& proTxHash) const
+ {
+ return GetValidMN(proTxHash) != nullptr;
+ }
+ bool HasMNByCollateral(const COutPoint& collateralOutpoint) const
+ {
+ return GetMNByCollateral(collateralOutpoint) != nullptr;
+ }
+ bool HasValidMNByCollateral(const COutPoint& collateralOutpoint) const
+ {
+ return GetValidMNByCollateral(collateralOutpoint) != nullptr;
+ }
CDeterministicMNCPtr GetMN(const uint256& proTxHash) const;
CDeterministicMNCPtr GetValidMN(const uint256& proTxHash) const;
CDeterministicMNCPtr GetMNByOperatorKey(const CBLSPublicKey& pubKey);
CDeterministicMNCPtr GetMNByCollateral(const COutPoint& collateralOutpoint) const;
+ CDeterministicMNCPtr GetValidMNByCollateral(const COutPoint& collateralOutpoint) const;
CDeterministicMNCPtr GetMNPayee() const;
/**
@@ -479,17 +492,12 @@ class CDeterministicMNManager
CDeterministicMNList GetListForBlock(const uint256& blockHash);
CDeterministicMNList GetListAtChainTip();
- // TODO remove after removal of old non-deterministic lists
- bool HasValidMNCollateralAtChainTip(const COutPoint& outpoint);
- bool HasMNCollateralAtChainTip(const COutPoint& outpoint);
-
// Test if given TX is a ProRegTx which also contains the collateral at index n
bool IsProTxWithCollateral(const CTransactionRef& tx, uint32_t n);
- bool IsDeterministicMNsSporkActive(int nHeight = -1);
+ bool IsDIP3Active(int nHeight);
private:
- int64_t GetSpork15Value();
void CleanupCache(int nHeight);
};
diff --git a/src/evo/providertx.cpp b/src/evo/providertx.cpp
index 9311968f7778..2dc5613755eb 100644
--- a/src/evo/providertx.cpp
+++ b/src/evo/providertx.cpp
@@ -177,7 +177,7 @@ bool CheckProRegTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValid
return state.DoS(10, false, REJECT_DUPLICATE, "bad-protx-dup-key");
}
- if (!deterministicMNManager->IsDeterministicMNsSporkActive(pindexPrev->nHeight)) {
+ if (!deterministicMNManager->IsDIP3Active(pindexPrev->nHeight)) {
if (ptx.keyIDOwner != ptx.keyIDVoting) {
return state.DoS(10, false, REJECT_INVALID, "bad-protx-key-not-same");
}
@@ -321,7 +321,7 @@ bool CheckProUpRegTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CVal
}
}
- if (!deterministicMNManager->IsDeterministicMNsSporkActive(pindexPrev->nHeight)) {
+ if (!deterministicMNManager->IsDIP3Active(pindexPrev->nHeight)) {
if (dmn->pdmnState->keyIDOwner != ptx.keyIDVoting) {
return state.DoS(10, false, REJECT_INVALID, "bad-protx-key-not-same");
}
diff --git a/src/governance-object.cpp b/src/governance-object.cpp
index ac026e268a07..09cfa94f771b 100644
--- a/src/governance-object.cpp
+++ b/src/governance-object.cpp
@@ -9,10 +9,12 @@
#include "governance-vote.h"
#include "governance.h"
#include "instantx.h"
+#include "masternode-meta.h"
#include "masternode-sync.h"
-#include "masternodeman.h"
#include "messagesigner.h"
+#include "spork.h"
#include "util.h"
+#include "validation.h"
#include
#include
@@ -116,14 +118,14 @@ bool CGovernanceObject::ProcessVote(CNode* pfrom,
return false;
}
- if (!mnodeman.Has(vote.GetMasternodeOutpoint())) {
+ auto mnList = deterministicMNManager->GetListAtChainTip();
+ auto dmn = mnList.GetValidMNByCollateral(vote.GetMasternodeOutpoint());
+
+ if (!dmn) {
std::ostringstream ostr;
ostr << "CGovernanceObject::ProcessVote -- Masternode " << vote.GetMasternodeOutpoint().ToStringShort() << " not found";
exception = CGovernanceException(ostr.str(), GOVERNANCE_EXCEPTION_WARNING);
if (cmmapOrphanVotes.Insert(vote.GetMasternodeOutpoint(), vote_time_pair_t(vote, GetAdjustedTime() + GOVERNANCE_ORPHAN_EXPIRATION_TIME))) {
- if (pfrom) {
- mnodeman.AskForMN(pfrom, vote.GetMasternodeOutpoint(), connman);
- }
LogPrintf("%s\n", ostr.str());
} else {
LogPrint("gobject", "%s\n", ostr.str());
@@ -192,7 +194,7 @@ bool CGovernanceObject::ProcessVote(CNode* pfrom,
return false;
}
- if (!mnodeman.AddGovernanceVote(vote.GetMasternodeOutpoint(), vote.GetParentHash())) {
+ if (!mmetaman.AddGovernanceVote(dmn->proTxHash, vote.GetParentHash())) {
std::ostringstream ostr;
ostr << "CGovernanceObject::ProcessVote -- Unable to add governance vote"
<< ", MN outpoint = " << vote.GetMasternodeOutpoint().ToStringShort()
@@ -212,9 +214,11 @@ void CGovernanceObject::ClearMasternodeVotes()
{
LOCK(cs);
+ auto mnList = deterministicMNManager->GetListAtChainTip();
+
vote_m_it it = mapCurrentMNVotes.begin();
while (it != mapCurrentMNVotes.end()) {
- if (!mnodeman.Has(it->first)) {
+ if (!mnList.HasValidMNByCollateral(it->first)) {
fileVotes.RemoveVotesFromMasternode(it->first);
mapCurrentMNVotes.erase(it++);
} else {
@@ -266,70 +270,6 @@ void CGovernanceObject::SetMasternodeOutpoint(const COutPoint& outpoint)
masternodeOutpoint = outpoint;
}
-bool CGovernanceObject::Sign(const CKey& key, const CKeyID& keyID)
-{
- std::string strError;
-
- if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
- uint256 hash = GetSignatureHash();
-
- if (!CHashSigner::SignHash(hash, key, vchSig)) {
- LogPrintf("CGovernanceObject::Sign -- SignHash() failed\n");
- return false;
- }
-
- if (!CHashSigner::VerifyHash(hash, keyID, vchSig, strError)) {
- LogPrintf("CGovernanceObject::Sign -- VerifyHash() failed, error: %s\n", strError);
- return false;
- }
- } else {
- std::string strMessage = GetSignatureMessage();
- if (!CMessageSigner::SignMessage(strMessage, vchSig, key)) {
- LogPrintf("CGovernanceObject::Sign -- SignMessage() failed\n");
- return false;
- }
-
- if (!CMessageSigner::VerifyMessage(keyID, vchSig, strMessage, strError)) {
- LogPrintf("CGovernanceObject::Sign -- VerifyMessage() failed, error: %s\n", strError);
- return false;
- }
- }
-
- LogPrint("gobject", "CGovernanceObject::Sign -- pubkey id = %s, masternode = %s\n",
- keyID.ToString(), masternodeOutpoint.ToStringShort());
-
- return true;
-}
-
-bool CGovernanceObject::CheckSignature(const CKeyID& keyID) const
-{
- std::string strError;
-
- if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
- uint256 hash = GetSignatureHash();
-
- if (!CHashSigner::VerifyHash(hash, keyID, vchSig, strError)) {
- // could be an old object
- std::string strMessage = GetSignatureMessage();
-
- if (!CMessageSigner::VerifyMessage(keyID, vchSig, strMessage, strError)) {
- // nope, not in old format either
- LogPrintf("CGovernance::CheckSignature -- VerifyMessage() failed, error: %s\n", strError);
- return false;
- }
- }
- } else {
- std::string strMessage = GetSignatureMessage();
-
- if (!CMessageSigner::VerifyMessage(keyID, vchSig, strMessage, strError)) {
- LogPrintf("CGovernance::CheckSignature -- VerifyMessage() failed, error: %s\n", strError);
- return false;
- }
- }
-
- return true;
-}
-
bool CGovernanceObject::Sign(const CBLSSecretKey& key)
{
CBLSSignature sig = key.Sign(GetSignatureHash());
@@ -507,36 +447,27 @@ bool CGovernanceObject::IsValidLocally(std::string& strError, bool& fMissingMast
return true;
}
+ auto mnList = deterministicMNManager->GetListAtChainTip();
+
std::string strOutpoint = masternodeOutpoint.ToStringShort();
- masternode_info_t infoMn;
- if (!mnodeman.GetMasternodeInfo(masternodeOutpoint, infoMn)) {
- CMasternode::CollateralStatus err = CMasternode::CheckCollateral(masternodeOutpoint, CKeyID());
- if (err == CMasternode::COLLATERAL_UTXO_NOT_FOUND) {
- strError = "Failed to find Masternode UTXO, missing masternode=" + strOutpoint + "\n";
- } else if (err == CMasternode::COLLATERAL_INVALID_AMOUNT) {
- strError = "Masternode UTXO should have 1000 DASH, missing masternode=" + strOutpoint + "\n";
- } else if (err == CMasternode::COLLATERAL_INVALID_PUBKEY) {
- fMissingMasternode = true;
- strError = "Masternode not found: " + strOutpoint;
- } else if (err == CMasternode::COLLATERAL_OK) {
- // this should never happen with CPubKey() as a param
- strError = "CheckCollateral critical failure! Masternode: " + strOutpoint;
+ auto dmn = mnList.GetMNByCollateral(masternodeOutpoint);
+ if (!dmn) {
+ strError = "Failed to find Masternode by UTXO, missing masternode=" + strOutpoint + "\n";
+ return false;
+ }
+ if (!mnList.IsMNValid(dmn)) {
+ if (mnList.IsMNPoSeBanned(dmn)) {
+ strError = "Masternode is POSE_BANNED, masternode=" + strOutpoint + "\n";
+ } else {
+ strError = "Masternode is invalid for unknown reason, masternode=" + strOutpoint + "\n";
}
-
return false;
}
// Check that we have a valid MN signature
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
- if (!CheckSignature(infoMn.blsPubKeyOperator)) {
- strError = "Invalid masternode signature for: " + strOutpoint + ", pubkey id = " + infoMn.blsPubKeyOperator.ToString();
- return false;
- }
- } else {
- if (!CheckSignature(infoMn.legacyKeyIDOperator)) {
- strError = "Invalid masternode signature for: " + strOutpoint + ", pubkey id = " + infoMn.legacyKeyIDOperator.ToString();
- return false;
- }
+ if (!CheckSignature(dmn->pdmnState->pubKeyOperator)) {
+ strError = "Invalid masternode signature for: " + strOutpoint + ", pubkey = " + dmn->pdmnState->pubKeyOperator.ToString();
+ return false;
}
return true;
@@ -734,7 +665,7 @@ void CGovernanceObject::UpdateSentinelVariables()
{
// CALCULATE MINIMUM SUPPORT LEVELS REQUIRED
- int nMnCount = mnodeman.CountEnabled();
+ int nMnCount = (int)deterministicMNManager->GetListAtChainTip().GetValidMNsCount();
if (nMnCount == 0) return;
// CALCULATE THE MINUMUM VOTE COUNT REQUIRED FOR FULL SIGNAL
@@ -767,6 +698,7 @@ void CGovernanceObject::UpdateSentinelVariables()
void CGovernanceObject::CheckOrphanVotes(CConnman& connman)
{
int64_t nNow = GetAdjustedTime();
+ auto mnList = deterministicMNManager->GetListAtChainTip();
const vote_cmm_t::list_t& listVotes = cmmapOrphanVotes.GetItemList();
vote_cmm_t::list_cit it = listVotes.begin();
while (it != listVotes.end()) {
@@ -776,7 +708,7 @@ void CGovernanceObject::CheckOrphanVotes(CConnman& connman)
const CGovernanceVote& vote = pairVote.first;
if (pairVote.second < nNow) {
fRemove = true;
- } else if (!mnodeman.Has(vote.GetMasternodeOutpoint())) {
+ } else if (!mnList.HasValidMNByCollateral(vote.GetMasternodeOutpoint())) {
++it;
continue;
}
@@ -793,41 +725,3 @@ void CGovernanceObject::CheckOrphanVotes(CConnman& connman)
}
}
}
-
-std::vector CGovernanceObject::RemoveOldVotes(unsigned int nMinTime)
-{
- LOCK(cs);
-
- // Drop pre-DIP3 votes from vote db
- auto removed = fileVotes.RemoveOldVotes(nMinTime);
-
- if (!removed.empty()) {
- std::string removedStr;
- for (auto& h : removed) {
- removedStr += strprintf(" %s\n", h.ToString());
- }
- LogPrintf("CGovernanceObject::RemoveOldVotes -- Removed %d old (pre-DIP3) votes for %s:\n%s\n", removed.size(), GetHash().ToString(), removedStr);
- fDirtyCache = true;
- }
-
- // Same for current votes per MN for this specific object
- auto itMnPair = mapCurrentMNVotes.begin();
- while (itMnPair != mapCurrentMNVotes.end()) {
- auto& miRef = itMnPair->second.mapInstances;
- auto itVotePair = miRef.begin();
- while (itVotePair != miRef.end()) {
- if (itVotePair->second.nCreationTime < nMinTime) {
- miRef.erase(itVotePair++);
- } else {
- ++itVotePair;
- }
- }
- if (miRef.empty()) {
- mapCurrentMNVotes.erase(itMnPair++);
- } else {
- ++itMnPair;
- }
- }
-
- return removed;
-}
diff --git a/src/governance-object.h b/src/governance-object.h
index 673491990693..fb2cc22f3652 100644
--- a/src/governance-object.h
+++ b/src/governance-object.h
@@ -259,8 +259,6 @@ class CGovernanceObject
// Signature related functions
void SetMasternodeOutpoint(const COutPoint& outpoint);
- bool Sign(const CKey& key, const CKeyID& keyID);
- bool CheckSignature(const CKeyID& keyID) const;
bool Sign(const CBLSSecretKey& key);
bool CheckSignature(const CBLSPublicKey& pubKey) const;
@@ -350,9 +348,6 @@ class CGovernanceObject
void ClearMasternodeVotes();
void CheckOrphanVotes(CConnman& connman);
-
- // TODO can be removed after DIP3 is fully deployed
- std::vector RemoveOldVotes(unsigned int nMinTime);
};
diff --git a/src/governance-vote.cpp b/src/governance-vote.cpp
index 15a145df12c4..cf8de873f1e1 100644
--- a/src/governance-vote.cpp
+++ b/src/governance-vote.cpp
@@ -5,10 +5,12 @@
#include "governance-vote.h"
#include "governance-object.h"
#include "masternode-sync.h"
-#include "masternodeman.h"
#include "messagesigner.h"
+#include "spork.h"
#include "util.h"
+#include "evo/deterministicmns.h"
+
std::string CGovernanceVoting::ConvertOutcomeToString(vote_outcome_enum_t nOutcome)
{
static const std::map mapOutcomeString = {
@@ -149,31 +151,16 @@ bool CGovernanceVote::Sign(const CKey& key, const CKeyID& keyID)
{
std::string strError;
- if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
- uint256 hash = GetSignatureHash();
+ uint256 hash = GetSignatureHash();
- if (!CHashSigner::SignHash(hash, key, vchSig)) {
- LogPrintf("CGovernanceVote::Sign -- SignHash() failed\n");
- return false;
- }
+ if (!CHashSigner::SignHash(hash, key, vchSig)) {
+ LogPrintf("CGovernanceVote::Sign -- SignHash() failed\n");
+ return false;
+ }
- if (!CHashSigner::VerifyHash(hash, keyID, vchSig, strError)) {
- LogPrintf("CGovernanceVote::Sign -- VerifyHash() failed, error: %s\n", strError);
- return false;
- }
- } else {
- std::string strMessage = masternodeOutpoint.ToStringShort() + "|" + nParentHash.ToString() + "|" +
- std::to_string(nVoteSignal) + "|" + std::to_string(nVoteOutcome) + "|" + std::to_string(nTime);
-
- if (!CMessageSigner::SignMessage(strMessage, vchSig, key)) {
- LogPrintf("CGovernanceVote::Sign -- SignMessage() failed\n");
- return false;
- }
-
- if (!CMessageSigner::VerifyMessage(keyID, vchSig, strMessage, strError)) {
- LogPrintf("CGovernanceVote::Sign -- VerifyMessage() failed, error: %s\n", strError);
- return false;
- }
+ if (!CHashSigner::VerifyHash(hash, keyID, vchSig, strError)) {
+ LogPrintf("CGovernanceVote::Sign -- VerifyHash() failed, error: %s\n", strError);
+ return false;
}
return true;
@@ -183,32 +170,11 @@ bool CGovernanceVote::CheckSignature(const CKeyID& keyID) const
{
std::string strError;
- if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
- uint256 hash = GetSignatureHash();
-
- if (!CHashSigner::VerifyHash(hash, keyID, vchSig, strError)) {
- // could be a signature in old format
- std::string strMessage = masternodeOutpoint.ToStringShort() + "|" + nParentHash.ToString() + "|" +
- std::to_string(nVoteSignal) + "|" +
- std::to_string(nVoteOutcome) + "|" +
- std::to_string(nTime);
-
- if (!CMessageSigner::VerifyMessage(keyID, vchSig, strMessage, strError)) {
- // nope, not in old format either
- LogPrint("gobject", "CGovernanceVote::IsValid -- VerifyMessage() failed, error: %s\n", strError);
- return false;
- }
- }
- } else {
- std::string strMessage = masternodeOutpoint.ToStringShort() + "|" + nParentHash.ToString() + "|" +
- std::to_string(nVoteSignal) + "|" +
- std::to_string(nVoteOutcome) + "|" +
- std::to_string(nTime);
-
- if (!CMessageSigner::VerifyMessage(keyID, vchSig, strMessage, strError)) {
- LogPrint("gobject", "CGovernanceVote::IsValid -- VerifyMessage() failed, error: %s\n", strError);
- return false;
- }
+ uint256 hash = GetSignatureHash();
+
+ if (!CHashSigner::VerifyHash(hash, keyID, vchSig, strError)) {
+ LogPrint("gobject", "CGovernanceVote::IsValid -- VerifyMessage() failed, error: %s\n", strError);
+ return false;
}
return true;
@@ -256,20 +222,16 @@ bool CGovernanceVote::IsValid(bool useVotingKey) const
return false;
}
- masternode_info_t infoMn;
- if (!mnodeman.GetMasternodeInfo(masternodeOutpoint, infoMn)) {
+ auto dmn = deterministicMNManager->GetListAtChainTip().GetValidMNByCollateral(masternodeOutpoint);
+ if (!dmn) {
LogPrint("gobject", "CGovernanceVote::IsValid -- Unknown Masternode - %s\n", masternodeOutpoint.ToStringShort());
return false;
}
if (useVotingKey) {
- return CheckSignature(infoMn.keyIDVoting);
+ return CheckSignature(dmn->pdmnState->keyIDVoting);
} else {
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
- return CheckSignature(infoMn.blsPubKeyOperator);
- } else {
- return CheckSignature(infoMn.legacyKeyIDOperator);
- }
+ return CheckSignature(dmn->pdmnState->pubKeyOperator);
}
}
diff --git a/src/governance.cpp b/src/governance.cpp
index a3cd27efd6fb..11e18d9b1d80 100644
--- a/src/governance.cpp
+++ b/src/governance.cpp
@@ -9,14 +9,15 @@
#include "governance-validators.h"
#include "governance-vote.h"
#include "init.h"
+#include "masternode-meta.h"
#include "masternode-sync.h"
-#include "masternode.h"
-#include "masternodeman.h"
#include "messagesigner.h"
#include "net_processing.h"
#include "netfulfilledman.h"
#include "netmessagemaker.h"
+#include "spork.h"
#include "util.h"
+#include "validation.h"
#include "validationinterface.h"
CGovernanceManager governance;
@@ -144,7 +145,7 @@ void CGovernanceManager::ProcessMessage(CNode* pfrom, const std::string& strComm
return;
}
- if (!masternodeSync.IsMasternodeListSynced()) {
+ if (!masternodeSync.IsBlockchainSynced()) {
LogPrint("gobject", "MNGOVERNANCEOBJECT -- masternode list not synced\n");
return;
}
@@ -222,12 +223,6 @@ void CGovernanceManager::ProcessMessage(CNode* pfrom, const std::string& strComm
CGovernanceVote vote;
vRecv >> vote;
- // TODO remove this check after full DIP3 deployment
- if (vote.GetTimestamp() < GetMinVoteTime()) {
- // Ignore votes pre-DIP3
- return;
- }
-
uint256 nHash = vote.GetHash();
{
@@ -241,7 +236,7 @@ void CGovernanceManager::ProcessMessage(CNode* pfrom, const std::string& strComm
}
// Ignore such messages until masternode list is synced
- if (!masternodeSync.IsMasternodeListSynced()) {
+ if (!masternodeSync.IsBlockchainSynced()) {
LogPrint("gobject", "MNGOVERNANCEOBJECTVOTE -- masternode list not synced\n");
return;
}
@@ -376,7 +371,7 @@ void CGovernanceManager::UpdateCachesAndClean()
{
LogPrint("gobject", "CGovernanceManager::UpdateCachesAndClean\n");
- std::vector vecDirtyHashes = mnodeman.GetAndClearDirtyGovernanceObjectHashes();
+ std::vector vecDirtyHashes = mmetaman.GetAndClearDirtyGovernanceObjectHashes();
LOCK2(cs_main, cs);
@@ -427,7 +422,7 @@ void CGovernanceManager::UpdateCachesAndClean()
if ((pObj->IsSetCachedDelete() || pObj->IsSetExpired()) &&
(nTimeSinceDeletion >= GOVERNANCE_DELETION_DELAY)) {
LogPrintf("CGovernanceManager::UpdateCachesAndClean -- erase obj %s\n", (*it).first.ToString());
- mnodeman.RemoveGovernanceObject(pObj->GetHash());
+ mmetaman.RemoveGovernanceObject(pObj->GetHash());
// Remove vote references
const object_ref_cm_t::list_t& listItems = cmapVoteToObject.GetItemList();
@@ -515,12 +510,17 @@ std::vector CGovernanceManager::GetCurrentVotes(const uint256&
if (it == mapObjects.end()) return vecResult;
const CGovernanceObject& govobj = it->second;
- CMasternode mn;
- std::map mapMasternodes;
+ auto mnList = deterministicMNManager->GetListAtChainTip();
+ std::map mapMasternodes;
if (mnCollateralOutpointFilter.IsNull()) {
- mapMasternodes = mnodeman.GetFullMasternodeMap();
- } else if (mnodeman.Get(mnCollateralOutpointFilter, mn)) {
- mapMasternodes[mnCollateralOutpointFilter] = mn;
+ mnList.ForEachMN(true, [&](const CDeterministicMNCPtr& dmn) {
+ mapMasternodes.emplace(dmn->collateralOutpoint, dmn);
+ });
+ } else {
+ auto dmn = mnList.GetValidMNByCollateral(mnCollateralOutpointFilter);
+ if (dmn) {
+ mapMasternodes.emplace(dmn->collateralOutpoint, dmn);
+ }
}
// Loop thru each MN collateral outpoint and get the votes for the `nParentHash` governance object
@@ -579,10 +579,6 @@ void CGovernanceManager::DoMaintenance(CConnman& connman)
{
if (fLiteMode || !masternodeSync.IsSynced() || ShutdownRequested()) return;
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
- ClearPreDIP3Votes();
- }
-
// CHECK OBJECTS WE'VE ASKED FOR, REMOVE OLD ENTRIES
CleanOrphanObjects();
@@ -597,7 +593,7 @@ void CGovernanceManager::DoMaintenance(CConnman& connman)
bool CGovernanceManager::ConfirmInventoryRequest(const CInv& inv)
{
// do not request objects until it's time to sync
- if (!masternodeSync.IsWinnersListSynced()) return false;
+ if (!masternodeSync.IsBlockchainSynced()) return false;
LOCK(cs);
@@ -1073,7 +1069,7 @@ int CGovernanceManager::RequestGovernanceObjectVotes(const std::vector&
int nMaxObjRequestsPerNode = 1;
size_t nProjectedVotes = 2000;
if (Params().NetworkIDString() != CBaseChainParams::MAIN) {
- nMaxObjRequestsPerNode = std::max(1, int(nProjectedVotes / std::max(1, mnodeman.size())));
+ nMaxObjRequestsPerNode = std::max(1, int(nProjectedVotes / std::max(1, (int)deterministicMNManager->GetListAtChainTip().GetValidMNsCount())));
}
{
@@ -1301,10 +1297,6 @@ void CGovernanceManager::UpdatedBlockTip(const CBlockIndex* pindex, CConnman& co
nCachedBlockHeight = pindex->nHeight;
LogPrint("gobject", "CGovernanceManager::UpdatedBlockTip -- nCachedBlockHeight: %d\n", nCachedBlockHeight);
- if (deterministicMNManager->IsDeterministicMNsSporkActive(pindex->nHeight)) {
- ClearPreDIP3Votes();
- }
-
CheckPostponedObjects(connman);
CSuperblockManager::ExecuteBestSuperblock(pindex->nHeight);
@@ -1356,37 +1348,3 @@ void CGovernanceManager::CleanOrphanObjects()
}
}
}
-
-unsigned int CGovernanceManager::GetMinVoteTime()
-{
- LOCK(cs_main);
- if (!deterministicMNManager->IsDeterministicMNsSporkActive()) {
- return 0;
- }
- int64_t dip3SporkHeight = sporkManager.GetSporkValue(SPORK_15_DETERMINISTIC_MNS_ENABLED);
- return chainActive[dip3SporkHeight]->nTime;
-}
-
-void CGovernanceManager::ClearPreDIP3Votes()
-{
- // This removes all votes which were created before DIP3 spork15 activation
- // All these votes are invalid immediately after spork15 activation due to the introduction of voting keys, which
- // are not equal to the old masternode private keys
-
- unsigned int minVoteTime = GetMinVoteTime();
-
- LOCK(cs);
- for (auto& p : mapObjects) {
- auto& obj = p.second;
- auto removed = obj.RemoveOldVotes(minVoteTime);
- if (removed.empty()) {
- continue;
- }
- for (auto& voteHash : removed) {
- cmapVoteToObject.Erase(voteHash);
- cmapInvalidVotes.Erase(voteHash);
- cmmapOrphanVotes.Erase(voteHash);
- setRequestedVotes.erase(voteHash);
- }
- }
-}
diff --git a/src/governance.h b/src/governance.h
index 6790c2b2edbf..6d07fdcafbbc 100644
--- a/src/governance.h
+++ b/src/governance.h
@@ -448,10 +448,6 @@ class CGovernanceManager
void RequestOrphanObjects(CConnman& connman);
void CleanOrphanObjects();
-
- // TODO can be removed after full DIP3 deployment
- unsigned int GetMinVoteTime();
- void ClearPreDIP3Votes();
};
#endif
diff --git a/src/init.cpp b/src/init.cpp
index 5bf399197a24..56549eee5a63 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -53,10 +53,10 @@
#ifdef ENABLE_WALLET
#include "keepass.h"
#endif
+#include "masternode-meta.h"
#include "masternode-payments.h"
#include "masternode-sync.h"
-#include "masternodeman.h"
-#include "masternodeconfig.h"
+#include "masternode-utils.h"
#include "messagesigner.h"
#include "netfulfilledman.h"
#ifdef ENABLE_WALLET
@@ -260,10 +260,8 @@ void PrepareShutdown()
if (!fLiteMode && !fRPCInWarmup) {
// STORE DATA CACHES INTO SERIALIZED DAT FILES
- CFlatDB flatdb1("mncache.dat", "magicMasternodeCache");
- flatdb1.Dump(mnodeman);
- CFlatDB flatdb2("mnpayments.dat", "magicMasternodePaymentsCache");
- flatdb2.Dump(mnpayments);
+ CFlatDB flatdb1("mncache.dat", "magicMasternodeMetaCache");
+ flatdb1.Dump(mmetaman);
CFlatDB flatdb3("governance.dat", "magicGovernanceCache");
flatdb3.Dump(governance);
CFlatDB flatdb4("netfulfilled.dat", "magicFulfilledCache");
@@ -589,9 +587,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageGroup(_("Masternode options:"));
strUsage += HelpMessageOpt("-masternode=", strprintf(_("Enable the client to act as a masternode (0-1, default: %u)"), 0));
- strUsage += HelpMessageOpt("-mnconf=", strprintf(_("Specify masternode configuration file (default: %s)"), "masternode.conf"));
- strUsage += HelpMessageOpt("-mnconflock=", strprintf(_("Lock masternodes from masternode configuration file (default: %u)"), 1));
- strUsage += HelpMessageOpt("-masternodeprivkey=", _("Set the masternode private key"));
+ strUsage += HelpMessageOpt("-masternodeblsprivkey=", _("Set the masternode BLS private key"));
#ifdef ENABLE_WALLET
strUsage += HelpMessageGroup(_("PrivateSend options:"));
@@ -1936,19 +1932,6 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler)
if(fMasternodeMode) {
LogPrintf("MASTERNODE:\n");
- std::string strMasterNodePrivKey = GetArg("-masternodeprivkey", "");
- if(!strMasterNodePrivKey.empty()) {
- CPubKey pubKeyMasternode;
- if(!CMessageSigner::GetKeysFromSecret(strMasterNodePrivKey, activeMasternodeInfo.legacyKeyOperator, pubKeyMasternode))
- return InitError(_("Invalid masternodeprivkey. Please see documenation."));
-
- activeMasternodeInfo.legacyKeyIDOperator = pubKeyMasternode.GetID();
-
- LogPrintf(" keyIDOperator: %s\n", CBitcoinAddress(activeMasternodeInfo.legacyKeyIDOperator).ToString());
- } else {
- return InitError(_("You must specify a masternodeprivkey in the configuration. Please see documentation for help."));
- }
-
std::string strMasterNodeBLSPrivKey = GetArg("-masternodeblsprivkey", "");
if(!strMasterNodeBLSPrivKey.empty()) {
auto binKey = ParseHex(strMasterNodeBLSPrivKey);
@@ -1966,7 +1949,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler)
}
// init and register activeMasternodeManager
- activeMasternodeManager = new CActiveDeterministicMasternodeManager();
+ activeMasternodeManager = new CActiveMasternodeManager();
RegisterValidationInterface(activeMasternodeManager);
}
@@ -1978,27 +1961,6 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler)
}
#ifdef ENABLE_WALLET
- LogPrintf("Using masternode config file %s\n", GetMasternodeConfigFile().string());
-
- if(GetBoolArg("-mnconflock", true) && pwalletMain && (masternodeConfig.getCount() > 0)) {
- LOCK(pwalletMain->cs_wallet);
- LogPrintf("Locking Masternodes:\n");
- uint256 mnTxHash;
- uint32_t outputIndex;
- for (const auto& mne : masternodeConfig.getEntries()) {
- mnTxHash.SetHex(mne.getTxHash());
- outputIndex = (uint32_t)atoi(mne.getOutputIndex());
- COutPoint outpoint = COutPoint(mnTxHash, outputIndex);
- // don't lock non-spendable outpoint (i.e. it's already spent or it's not from this wallet at all)
- if(pwalletMain->IsMine(CTxIn(outpoint)) != ISMINE_SPENDABLE) {
- LogPrintf(" %s %s - IS NOT SPENDABLE, was not locked\n", mne.getTxHash(), mne.getOutputIndex());
- continue;
- }
- pwalletMain->LockCoin(outpoint);
- LogPrintf(" %s %s - locked successfully\n", mne.getTxHash(), mne.getOutputIndex());
- }
- }
-
// ********************************************************* Step 11b: setup PrivateSend
privateSendClient.nLiquidityProvider = std::min(std::max((int)GetArg("-liquidityprovider", DEFAULT_PRIVATESEND_LIQUIDITY), MIN_PRIVATESEND_LIQUIDITY), MAX_PRIVATESEND_LIQUIDITY);
@@ -2036,29 +1998,18 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler)
strDBName = "mncache.dat";
uiInterface.InitMessage(_("Loading masternode cache..."));
- CFlatDB flatdb1(strDBName, "magicMasternodeCache");
- if(!flatdb1.Load(mnodeman)) {
+ CFlatDB flatdb1(strDBName, "magicMasternodeMetaCache");
+ if(!flatdb1.Load(mmetaman)) {
return InitError(_("Failed to load masternode cache from") + "\n" + (pathDB / strDBName).string());
}
- if(mnodeman.size()) {
- strDBName = "mnpayments.dat";
- uiInterface.InitMessage(_("Loading masternode payment cache..."));
- CFlatDB flatdb2(strDBName, "magicMasternodePaymentsCache");
- if(!flatdb2.Load(mnpayments)) {
- return InitError(_("Failed to load masternode payments cache from") + "\n" + (pathDB / strDBName).string());
- }
-
- strDBName = "governance.dat";
- uiInterface.InitMessage(_("Loading governance cache..."));
- CFlatDB flatdb3(strDBName, "magicGovernanceCache");
- if(!flatdb3.Load(governance)) {
- return InitError(_("Failed to load governance cache from") + "\n" + (pathDB / strDBName).string());
- }
- governance.InitOnLoad();
- } else {
- uiInterface.InitMessage(_("Masternode cache is empty, skipping payments and governance cache..."));
+ strDBName = "governance.dat";
+ uiInterface.InitMessage(_("Loading governance cache..."));
+ CFlatDB flatdb3(strDBName, "magicGovernanceCache");
+ if(!flatdb3.Load(governance)) {
+ return InitError(_("Failed to load governance cache from") + "\n" + (pathDB / strDBName).string());
}
+ governance.InitOnLoad();
strDBName = "netfulfilled.dat";
uiInterface.InitMessage(_("Loading fulfilled requests cache..."));
@@ -2083,10 +2034,8 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler)
if (!fLiteMode) {
scheduler.scheduleEvery(boost::bind(&CNetFulfilledRequestManager::DoMaintenance, boost::ref(netfulfilledman)), 60);
scheduler.scheduleEvery(boost::bind(&CMasternodeSync::DoMaintenance, boost::ref(masternodeSync), boost::ref(*g_connman)), 1);
- scheduler.scheduleEvery(boost::bind(&CMasternodeMan::DoMaintenance, boost::ref(mnodeman), boost::ref(*g_connman)), 1);
- scheduler.scheduleEvery(boost::bind(&CActiveLegacyMasternodeManager::DoMaintenance, boost::ref(legacyActiveMasternodeManager), boost::ref(*g_connman)), MASTERNODE_MIN_MNP_SECONDS);
+ scheduler.scheduleEvery(boost::bind(&CMasternodeUtils::DoMaintenance, boost::ref(*g_connman)), 1);
- scheduler.scheduleEvery(boost::bind(&CMasternodePayments::DoMaintenance, boost::ref(mnpayments)), 60);
scheduler.scheduleEvery(boost::bind(&CGovernanceManager::DoMaintenance, boost::ref(governance), boost::ref(*g_connman)), 60 * 5);
scheduler.scheduleEvery(boost::bind(&CInstantSend::DoMaintenance, boost::ref(instantsend)), 60);
diff --git a/src/instantx.cpp b/src/instantx.cpp
index 49bd568528aa..296ca8c60b94 100644
--- a/src/instantx.cpp
+++ b/src/instantx.cpp
@@ -9,7 +9,7 @@
#include "validation.h"
#include "masternode-payments.h"
#include "masternode-sync.h"
-#include "masternodeman.h"
+#include "masternode-utils.h"
#include "messagesigner.h"
#include "net.h"
#include "netmessagemaker.h"
@@ -79,8 +79,8 @@ void CInstantSend::ProcessMessage(CNode* pfrom, const std::string& strCommand, C
connman.RemoveAskFor(nVoteHash);
}
- // Ignore any InstantSend messages until masternode list is synced
- if (!masternodeSync.IsMasternodeListSynced()) return;
+ // Ignore any InstantSend messages until blockchain is synced
+ if (!masternodeSync.IsBlockchainSynced()) return;
{
LOCK(cs_instantsend);
@@ -245,15 +245,10 @@ void CInstantSend::Vote(CTxLockCandidate& txLockCandidate, CConnman& connman)
int nRank;
uint256 quorumModifierHash;
- int nMinRequiredProtocol = std::max(MIN_INSTANTSEND_PROTO_VERSION, mnpayments.GetMinMasternodePaymentsProto());
- if (!mnodeman.GetMasternodeRank(activeMasternodeInfo.outpoint, nRank, quorumModifierHash, nLockInputHeight, nMinRequiredProtocol)) {
+ if (!CMasternodeUtils::GetMasternodeRank(activeMasternodeInfo.outpoint, nRank, quorumModifierHash, nLockInputHeight)) {
LogPrint("instantsend", "CInstantSend::Vote -- Can't calculate rank for masternode %s\n", activeMasternodeInfo.outpoint.ToStringShort());
continue;
}
- if (!deterministicMNManager->IsDeterministicMNsSporkActive()) {
- // not used until spork15 activation
- quorumModifierHash = uint256();
- }
int nSignaturesTotal = COutPointLock::SIGNATURES_TOTAL;
if (nRank > nSignaturesTotal) {
@@ -469,7 +464,8 @@ void CInstantSend::UpdateVotedOutpoints(const CTxLockVote& vote, CTxLockCandidat
txLockCandidate.MarkOutpointAsAttacked(vote.GetOutpoint());
it2->second.MarkOutpointAsAttacked(vote.GetOutpoint());
// apply maximum PoSe ban score to this masternode i.e. PoSe-ban it instantly
- mnodeman.PoSeBan(vote.GetMasternodeOutpoint());
+ // TODO Call new PoSe system when it's ready
+ //mnodeman.PoSeBan(vote.GetMasternodeOutpoint());
// NOTE: This vote must be relayed further to let all other nodes know about such
// misbehaviour of this masternode. This way they should also be able to construct
// conflicting lock and PoSe-ban this masternode.
@@ -666,7 +662,7 @@ int64_t CInstantSend::GetAverageMasternodeOrphanVoteTime()
void CInstantSend::CheckAndRemove()
{
- if (!masternodeSync.IsMasternodeListSynced()) return;
+ if (!masternodeSync.IsBlockchainSynced()) return;
LOCK(cs_instantsend);
@@ -1029,22 +1025,24 @@ bool CTxLockRequest::IsSimple() const
bool CTxLockVote::IsValid(CNode* pnode, CConnman& connman) const
{
- if (!mnodeman.Has(outpointMasternode)) {
+ auto mnList = deterministicMNManager->GetListAtChainTip();
+
+ if (!mnList.HasValidMNByCollateral(outpointMasternode)) {
LogPrint("instantsend", "CTxLockVote::IsValid -- Unknown masternode %s\n", outpointMasternode.ToStringShort());
- mnodeman.AskForMN(pnode, outpointMasternode, connman);
return false;
}
// Verify that masternodeProTxHash belongs to the same MN referred by the collateral
- // Only v13 nodes will send us locks with this field set, and only after spork15 activation
+ // This is a leftover from the legacy non-deterministic MN list where we used the collateral to identify MNs
+ // TODO eventually remove the collateral from CTxLockVote
if (!masternodeProTxHash.IsNull()) {
- masternode_info_t mnInfo;
- if (!mnodeman.GetMasternodeInfo(masternodeProTxHash, mnInfo) || mnInfo.outpoint != outpointMasternode) {
+ auto dmn = mnList.GetValidMN(masternodeProTxHash);
+ if (!dmn || dmn->collateralOutpoint != outpointMasternode) {
LogPrint("instantsend", "CTxLockVote::IsValid -- invalid masternodeProTxHash %s\n", masternodeProTxHash.ToString());
return false;
}
- } else if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
- LogPrint("instantsend", "CTxLockVote::IsValid -- missing masternodeProTxHash while DIP3 is active\n");
+ } else {
+ LogPrint("instantsend", "CTxLockVote::IsValid -- missing masternodeProTxHash\n");
return false;
}
@@ -1058,8 +1056,7 @@ bool CTxLockVote::IsValid(CNode* pnode, CConnman& connman) const
int nRank;
uint256 expectedQuorumModifierHash;
- int nMinRequiredProtocol = std::max(MIN_INSTANTSEND_PROTO_VERSION, mnpayments.GetMinMasternodePaymentsProto());
- if (!mnodeman.GetMasternodeRank(outpointMasternode, nRank, expectedQuorumModifierHash, nLockInputHeight, nMinRequiredProtocol)) {
+ if (!CMasternodeUtils::GetMasternodeRank(outpointMasternode, nRank, expectedQuorumModifierHash, nLockInputHeight)) {
//can be caused by past versions trying to vote with an invalid protocol
LogPrint("instantsend", "CTxLockVote::IsValid -- Can't calculate rank for masternode %s\n", outpointMasternode.ToStringShort());
return false;
@@ -1069,8 +1066,8 @@ bool CTxLockVote::IsValid(CNode* pnode, CConnman& connman) const
LogPrint("instantsend", "CTxLockVote::IsValid -- invalid quorumModifierHash %s, expected %s\n", quorumModifierHash.ToString(), expectedQuorumModifierHash.ToString());
return false;
}
- } else if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
- LogPrint("instantsend", "CTxLockVote::IsValid -- missing quorumModifierHash while DIP3 is active\n");
+ } else {
+ LogPrint("instantsend", "CTxLockVote::IsValid -- missing quorumModifierHash\n");
return false;
}
@@ -1105,42 +1102,20 @@ bool CTxLockVote::CheckSignature() const
{
std::string strError;
- masternode_info_t infoMn;
-
- if (!mnodeman.GetMasternodeInfo(outpointMasternode, infoMn)) {
- LogPrintf("CTxLockVote::CheckSignature -- Unknown Masternode: masternode=%s\n", outpointMasternode.ToString());
+ auto dmn = deterministicMNManager->GetListAtChainTip().GetValidMN(masternodeProTxHash);
+ if (!dmn) {
+ LogPrintf("CTxLockVote::CheckSignature -- Unknown Masternode: masternode=%s\n", masternodeProTxHash.ToString());
return false;
}
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
- uint256 hash = GetSignatureHash();
+ uint256 hash = GetSignatureHash();
- CBLSSignature sig;
- sig.SetBuf(vchMasternodeSignature);
- if (!sig.IsValid() || !sig.VerifyInsecure(infoMn.blsPubKeyOperator, hash)) {
- LogPrintf("CTxLockVote::CheckSignature -- VerifyInsecure() failed\n");
- return false;
- }
- } else if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
- uint256 hash = GetSignatureHash();
-
- if (!CHashSigner::VerifyHash(hash, infoMn.legacyKeyIDOperator, vchMasternodeSignature, strError)) {
- // could be a signature in old format
- std::string strMessage = txHash.ToString() + outpoint.ToStringShort();
- if (!CMessageSigner::VerifyMessage(infoMn.legacyKeyIDOperator, vchMasternodeSignature, strMessage, strError)) {
- // nope, not in old format either
- LogPrintf("CTxLockVote::CheckSignature -- VerifyMessage() failed, error: %s\n", strError);
- return false;
- }
- }
- } else {
- std::string strMessage = txHash.ToString() + outpoint.ToStringShort();
- if (!CMessageSigner::VerifyMessage(infoMn.legacyKeyIDOperator, vchMasternodeSignature, strMessage, strError)) {
- LogPrintf("CTxLockVote::CheckSignature -- VerifyMessage() failed, error: %s\n", strError);
- return false;
- }
+ CBLSSignature sig;
+ sig.SetBuf(vchMasternodeSignature);
+ if (!sig.IsValid() || !sig.VerifyInsecure(dmn->pdmnState->pubKeyOperator, hash)) {
+ LogPrintf("CTxLockVote::CheckSignature -- VerifyInsecure() failed\n");
+ return false;
}
-
return true;
}
@@ -1148,40 +1123,13 @@ bool CTxLockVote::Sign()
{
std::string strError;
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
- uint256 hash = GetSignatureHash();
-
- CBLSSignature sig = activeMasternodeInfo.blsKeyOperator->Sign(hash);
- if (!sig.IsValid()) {
- return false;
- }
- sig.GetBuf(vchMasternodeSignature);
- } else if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
- uint256 hash = GetSignatureHash();
-
- if (!CHashSigner::SignHash(hash, activeMasternodeInfo.legacyKeyOperator, vchMasternodeSignature)) {
- LogPrintf("CTxLockVote::Sign -- SignHash() failed\n");
- return false;
- }
-
- if (!CHashSigner::VerifyHash(hash, activeMasternodeInfo.legacyKeyIDOperator, vchMasternodeSignature, strError)) {
- LogPrintf("CTxLockVote::Sign -- VerifyHash() failed, error: %s\n", strError);
- return false;
- }
- } else {
- std::string strMessage = txHash.ToString() + outpoint.ToStringShort();
-
- if (!CMessageSigner::SignMessage(strMessage, vchMasternodeSignature, activeMasternodeInfo.legacyKeyOperator)) {
- LogPrintf("CTxLockVote::Sign -- SignMessage() failed\n");
- return false;
- }
+ uint256 hash = GetSignatureHash();
- if (!CMessageSigner::VerifyMessage(activeMasternodeInfo.legacyKeyIDOperator, vchMasternodeSignature, strMessage, strError)) {
- LogPrintf("CTxLockVote::Sign -- VerifyMessage() failed, error: %s\n", strError);
- return false;
- }
+ CBLSSignature sig = activeMasternodeInfo.blsKeyOperator->Sign(hash);
+ if (!sig.IsValid()) {
+ return false;
}
-
+ sig.GetBuf(vchMasternodeSignature);
return true;
}
diff --git a/src/instantx.h b/src/instantx.h
index 81f18c23b66c..dccdb52e9758 100644
--- a/src/instantx.h
+++ b/src/instantx.h
@@ -233,7 +233,7 @@ class CTxLockVote
private:
uint256 txHash;
COutPoint outpoint;
- // TODO remove this member when the legacy masternode code is removed after DIP3 deployment
+ // TODO remove this member (not needed anymore after DIP3 has been deployed)
COutPoint outpointMasternode;
uint256 quorumModifierHash;
uint256 masternodeProTxHash;
@@ -272,12 +272,8 @@ class CTxLockVote
READWRITE(txHash);
READWRITE(outpoint);
READWRITE(outpointMasternode);
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
- // Starting with spork15 activation, the proTxHash and quorumModifierHash is included. When we bump to >= 70214, we can remove
- // the surrounding if. We might also remove outpointMasternode as well later
- READWRITE(quorumModifierHash);
- READWRITE(masternodeProTxHash);
- }
+ READWRITE(quorumModifierHash);
+ READWRITE(masternodeProTxHash);
if (!(s.GetType() & SER_GETHASH)) {
READWRITE(vchMasternodeSignature);
}
diff --git a/src/masternode-meta.cpp b/src/masternode-meta.cpp
new file mode 100644
index 000000000000..ec00845c12a9
--- /dev/null
+++ b/src/masternode-meta.cpp
@@ -0,0 +1,124 @@
+// Copyright (c) 2014-2018 The Dash Core developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "masternode-meta.h"
+
+CMasternodeMetaMan mmetaman;
+
+const std::string CMasternodeMetaMan::SERIALIZATION_VERSION_STRING = "CMasternodeMetaMan-Version-1";
+
+void CMasternodeMetaInfo::AddGovernanceVote(const uint256& nGovernanceObjectHash)
+{
+ LOCK(cs);
+ // Insert a zero value, or not. Then increment the value regardless. This
+ // ensures the value is in the map.
+ const auto& pair = mapGovernanceObjectsVotedOn.emplace(nGovernanceObjectHash, 0);
+ pair.first->second++;
+}
+
+void CMasternodeMetaInfo::RemoveGovernanceObject(const uint256& nGovernanceObjectHash)
+{
+ LOCK(cs);
+ // Whether or not the govobj hash exists in the map first is irrelevant.
+ mapGovernanceObjectsVotedOn.erase(nGovernanceObjectHash);
+}
+
+/**
+* FLAG GOVERNANCE ITEMS AS DIRTY
+*
+* - When masternode come and go on the network, we must flag the items they voted on to recalc it's cached flags
+*
+*/
+void CMasternodeMetaInfo::FlagGovernanceItemsAsDirty()
+{
+ LOCK(cs);
+ for (auto& govObjHashPair : mapGovernanceObjectsVotedOn) {
+ mmetaman.AddDirtyGovernanceObjectHash(govObjHashPair.first);
+ }
+}
+
+CMasternodeMetaInfoPtr CMasternodeMetaMan::GetMetaInfo(const uint256& proTxHash, bool fCreate)
+{
+ LOCK(cs);
+ auto it = metaInfos.find(proTxHash);
+ if (it != metaInfos.end()) {
+ return it->second;
+ }
+ if (!fCreate) {
+ return nullptr;
+ }
+ it = metaInfos.emplace(proTxHash, std::make_shared(proTxHash)).first;
+ return it->second;
+}
+
+void CMasternodeMetaMan::AllowMixing(const uint256& proTxHash)
+{
+ LOCK(cs);
+ auto mm = GetMetaInfo(proTxHash);
+ nDsqCount++;
+ LOCK(mm->cs);
+ mm->nLastDsq = nDsqCount;
+ mm->nMixingTxCount = 0;
+}
+
+void CMasternodeMetaMan::DisallowMixing(const uint256& proTxHash)
+{
+ LOCK(cs);
+ auto mm = GetMetaInfo(proTxHash);
+
+ LOCK(mm->cs);
+ mm->nMixingTxCount++;
+}
+
+bool CMasternodeMetaMan::AddGovernanceVote(const uint256& proTxHash, const uint256& nGovernanceObjectHash)
+{
+ LOCK(cs);
+ auto mm = GetMetaInfo(proTxHash);
+ mm->AddGovernanceVote(nGovernanceObjectHash);
+ return true;
+}
+
+void CMasternodeMetaMan::RemoveGovernanceObject(const uint256& nGovernanceObjectHash)
+{
+ LOCK(cs);
+ for(auto& p : metaInfos) {
+ p.second->RemoveGovernanceObject(nGovernanceObjectHash);
+ }
+}
+
+void CMasternodeMetaMan::AddDirtyGovernanceObjectHash(const uint256& nHash)
+{
+ LOCK(cs);
+ vecDirtyGovernanceObjectHashes.push_back(nHash);
+}
+
+std::vector CMasternodeMetaMan::GetAndClearDirtyGovernanceObjectHashes()
+{
+ LOCK(cs);
+ std::vector vecTmp = std::move(vecDirtyGovernanceObjectHashes);
+ vecDirtyGovernanceObjectHashes.clear();
+ return vecTmp;
+}
+
+void CMasternodeMetaMan::Clear()
+{
+ LOCK(cs);
+ metaInfos.clear();
+ vecDirtyGovernanceObjectHashes.clear();
+}
+
+void CMasternodeMetaMan::CheckAndRemove()
+{
+
+}
+
+std::string CMasternodeMetaMan::ToString() const
+{
+ std::ostringstream info;
+
+ info << "Masternodes: meta infos object count: " << (int)metaInfos.size() <<
+ ", deterministic masternode count: " << deterministicMNManager->GetListAtChainTip().GetAllMNsCount() <<
+ ", nDsqCount: " << (int)nDsqCount;
+ return info.str();
+}
diff --git a/src/masternode-meta.h b/src/masternode-meta.h
new file mode 100644
index 000000000000..f60d5dd55682
--- /dev/null
+++ b/src/masternode-meta.h
@@ -0,0 +1,153 @@
+// Copyright (c) 2014-2018 The Dash Core developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef MASTERNODE_META_H
+#define MASTERNODE_META_H
+
+#include "serialize.h"
+
+#include "evo/deterministicmns.h"
+
+#include
+
+class CConnman;
+
+static const int MASTERNODE_MAX_MIXING_TXES = 5;
+
+// Holds extra (non-deterministic) information about masternodes
+// This is mostly local information, e.g. about mixing and governance
+class CMasternodeMetaInfo
+{
+ friend class CMasternodeMetaMan;
+
+private:
+ mutable CCriticalSection cs;
+
+ uint256 proTxHash;
+
+ //the dsq count from the last dsq broadcast of this node
+ int64_t nLastDsq = 0;
+ int nMixingTxCount = 0;
+
+ // KEEP TRACK OF GOVERNANCE ITEMS EACH MASTERNODE HAS VOTE UPON FOR RECALCULATION
+ std::map mapGovernanceObjectsVotedOn;
+
+public:
+ CMasternodeMetaInfo() {}
+ CMasternodeMetaInfo(const uint256& _proTxHash) : proTxHash(_proTxHash) {}
+ CMasternodeMetaInfo(const CMasternodeMetaInfo& ref) :
+ proTxHash(ref.proTxHash),
+ nLastDsq(ref.nLastDsq),
+ nMixingTxCount(ref.nMixingTxCount),
+ mapGovernanceObjectsVotedOn(ref.mapGovernanceObjectsVotedOn)
+ {
+ }
+
+ template
+ CMasternodeMetaInfo(deserialize_type, Stream& s)
+ {
+ s >> *this;
+ }
+
+ ADD_SERIALIZE_METHODS
+ template
+ inline void SerializationOp(Stream& s, Operation ser_action)
+ {
+ LOCK(cs);
+ READWRITE(proTxHash);
+ READWRITE(nLastDsq);
+ READWRITE(nMixingTxCount);
+ READWRITE(mapGovernanceObjectsVotedOn);
+ }
+
+public:
+ const uint256& GetProTxHash() const { LOCK(cs); return proTxHash; }
+ int64_t GetLastDsq() const { LOCK(cs); return nLastDsq; }
+ int GetMixingTxCount() const { LOCK(cs); return nMixingTxCount; }
+
+ bool IsValidForMixingTxes() const { return GetMixingTxCount() <= MASTERNODE_MAX_MIXING_TXES; }
+
+ // KEEP TRACK OF EACH GOVERNANCE ITEM INCASE THIS NODE GOES OFFLINE, SO WE CAN RECALC THEIR STATUS
+ void AddGovernanceVote(const uint256& nGovernanceObjectHash);
+ // RECALCULATE CACHED STATUS FLAGS FOR ALL AFFECTED OBJECTS
+ void FlagGovernanceItemsAsDirty();
+
+ void RemoveGovernanceObject(const uint256& nGovernanceObjectHash);
+};
+typedef std::shared_ptr CMasternodeMetaInfoPtr;
+
+class CMasternodeMetaMan
+{
+private:
+ static const std::string SERIALIZATION_VERSION_STRING;
+
+ CCriticalSection cs;
+
+ std::map metaInfos;
+ std::vector vecDirtyGovernanceObjectHashes;
+
+ // keep track of dsq count to prevent masternodes from gaming privatesend queue
+ int64_t nDsqCount = 0;
+
+public:
+ ADD_SERIALIZE_METHODS
+
+ template
+ inline void SerializationOp(Stream& s, Operation ser_action)
+ {
+ LOCK(cs);
+
+ std::string strVersion;
+ if(ser_action.ForRead()) {
+ READWRITE(strVersion);
+ }
+ else {
+ strVersion = SERIALIZATION_VERSION_STRING;
+ READWRITE(strVersion);
+ }
+
+ std::vector tmpMetaInfo;
+ if (ser_action.ForRead()) {
+ READWRITE(tmpMetaInfo);
+ metaInfos.clear();
+ for (auto& mm : tmpMetaInfo) {
+ metaInfos.emplace(mm.GetProTxHash(), std::make_shared(std::move(mm)));
+ }
+ } else {
+ for (auto& p : metaInfos) {
+ tmpMetaInfo.emplace_back(*p.second);
+ }
+ READWRITE(tmpMetaInfo);
+ }
+
+ READWRITE(nDsqCount);
+
+ if(ser_action.ForRead() && (strVersion != SERIALIZATION_VERSION_STRING)) {
+ Clear();
+ }
+ }
+
+public:
+ CMasternodeMetaInfoPtr GetMetaInfo(const uint256& proTxHash, bool fCreate = true);
+
+ int64_t GetDsqCount() { LOCK(cs); return nDsqCount; }
+
+ void AllowMixing(const uint256& proTxHash);
+ void DisallowMixing(const uint256& proTxHash);
+
+ bool AddGovernanceVote(const uint256& proTxHash, const uint256& nGovernanceObjectHash);
+ void RemoveGovernanceObject(const uint256& nGovernanceObjectHash);
+
+ void AddDirtyGovernanceObjectHash(const uint256& nHash);
+ std::vector GetAndClearDirtyGovernanceObjectHashes();
+
+ void Clear();
+ void CheckAndRemove();
+
+ std::string ToString() const;
+};
+
+extern CMasternodeMetaMan mmetaman;
+
+#endif//MASTERNODE_META_H
diff --git a/src/masternode-payments.cpp b/src/masternode-payments.cpp
index 61da6eaeb62a..f320e32816c3 100644
--- a/src/masternode-payments.cpp
+++ b/src/masternode-payments.cpp
@@ -8,24 +8,19 @@
#include "init.h"
#include "masternode-payments.h"
#include "masternode-sync.h"
-#include "masternodeman.h"
#include "messagesigner.h"
#include "netfulfilledman.h"
#include "netmessagemaker.h"
#include "spork.h"
#include "util.h"
+#include "validation.h"
#include "evo/deterministicmns.h"
#include
-/** Object for who's going to get paid on which blocks */
CMasternodePayments mnpayments;
-CCriticalSection cs_vecPayees;
-CCriticalSection cs_mapMasternodeBlocks;
-CCriticalSection cs_mapMasternodePaymentVotes;
-
bool IsOldBudgetBlockValueValid(const CBlock& block, int nBlockHeight, CAmount blockReward, std::string& strErrorRet) {
const Consensus::Params& consensusParams = Params().GetConsensus();
bool isBlockRewardValueMet = (block.vtx[0]->GetValueOut() <= blockReward);
@@ -167,7 +162,7 @@ bool IsBlockValueValid(const CBlock& block, int nBlockHeight, CAmount blockRewar
bool IsBlockPayeeValid(const CTransaction& txNew, int nBlockHeight, CAmount blockReward)
{
- if((!masternodeSync.IsSynced() && !deterministicMNManager->IsDeterministicMNsSporkActive(nBlockHeight)) || fLiteMode) {
+ if(fLiteMode) {
//there is no budget data to use to check anything, let's just accept the longest chain
if(fDebug) LogPrintf("%s -- WARNING: Not enough data, skipping block payee checks\n", __func__);
return true;
@@ -193,9 +188,6 @@ bool IsBlockPayeeValid(const CTransaction& txNew, int nBlockHeight, CAmount bloc
if(CSuperblockManager::IsSuperblockTriggered(nBlockHeight)) {
if(CSuperblockManager::IsValid(txNew, nBlockHeight, blockReward)) {
LogPrint("gobject", "%s -- Valid superblock at height %d: %s", __func__, nBlockHeight, txNew.ToString());
- // only allow superblock and masternode payments in the same block after spork15 activation
- if (!deterministicMNManager->IsDeterministicMNsSporkActive(nBlockHeight))
- return true;
// continue validation, should also pay MN
} else {
LogPrintf("%s -- ERROR: Invalid superblock detected at height %d: %s", __func__, nBlockHeight, txNew.ToString());
@@ -210,24 +202,14 @@ bool IsBlockPayeeValid(const CTransaction& txNew, int nBlockHeight, CAmount bloc
LogPrint("gobject", "%s -- Superblocks are disabled, no superblocks allowed\n", __func__);
}
- // If this isn't a superblock or spork15 is activated, check for correct masternode payment
+ // Check for correct masternode payment
if(mnpayments.IsTransactionValid(txNew, nBlockHeight, blockReward)) {
LogPrint("mnpayments", "%s -- Valid masternode payment at height %d: %s", __func__, nBlockHeight, txNew.ToString());
return true;
}
- if (deterministicMNManager->IsDeterministicMNsSporkActive(nBlockHeight)) {
- // always enforce masternode payments when spork15 is active
- return false;
- } else {
- if(sporkManager.IsSporkActive(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT)) {
- LogPrintf("%s -- ERROR: Invalid masternode payment detected at height %d: %s", __func__, nBlockHeight, txNew.ToString());
- return false;
- }
-
- LogPrintf("%s-- WARNING: Masternode payment enforcement is disabled, accepting any payee\n", __func__);
- return true;
- }
+ LogPrintf("%s -- ERROR: Invalid masternode payment detected at height %d: %s", __func__, nBlockHeight, txNew.ToString());
+ return false;
}
void FillBlockPayments(CMutableTransaction& txNew, int nBlockHeight, CAmount blockReward, std::vector& voutMasternodePaymentsRet, std::vector& voutSuperblockPaymentsRet)
@@ -240,14 +222,6 @@ void FillBlockPayments(CMutableTransaction& txNew, int nBlockHeight, CAmount blo
CSuperblockManager::GetSuperblockPayments(nBlockHeight, voutSuperblockPaymentsRet);
}
- bool allowSuperblockAndMNReward = deterministicMNManager->IsDeterministicMNsSporkActive(nBlockHeight);
-
- // don't allow payments to superblocks AND masternodes before spork15 activation
- if (!voutSuperblockPaymentsRet.empty() && !allowSuperblockAndMNReward) {
- txNew.vout.insert(txNew.vout.end(), voutSuperblockPaymentsRet.begin(), voutSuperblockPaymentsRet.end());
- return;
- }
-
if (!mnpayments.GetMasternodeTxOuts(nBlockHeight, blockReward, voutMasternodePaymentsRet)) {
LogPrint("mnpayments", "%s -- no masternode to pay (MN list probably empty)\n", __func__);
}
@@ -268,17 +242,6 @@ void FillBlockPayments(CMutableTransaction& txNew, int nBlockHeight, CAmount blo
nBlockHeight, blockReward, voutMasternodeStr, txNew.ToString());
}
-std::string GetLegacyRequiredPaymentsString(int nBlockHeight)
-{
- // IF WE HAVE A ACTIVATED TRIGGER FOR THIS HEIGHT - IT IS A SUPERBLOCK, GET THE REQUIRED PAYEES
- if(CSuperblockManager::IsSuperblockTriggered(nBlockHeight)) {
- return CSuperblockManager::GetRequiredPaymentsString(nBlockHeight);
- }
-
- // OTHERWISE, PAY MASTERNODE
- return mnpayments.GetRequiredPaymentsString(nBlockHeight);
-}
-
std::string GetRequiredPaymentsString(int nBlockHeight, const CDeterministicMNCPtr &payee)
{
std::string strPayee = "Unknown";
@@ -303,16 +266,12 @@ std::map GetRequiredPaymentsStrings(int nStartHeight, int nEnd
bool doProjection = false;
for(int h = nStartHeight; h < nEndHeight; h++) {
- if (deterministicMNManager->IsDeterministicMNsSporkActive(h)) {
- if (h <= nChainTipHeight) {
- auto payee = deterministicMNManager->GetListForBlock(chainActive[h - 1]->GetBlockHash()).GetMNPayee();
- mapPayments.emplace(h, GetRequiredPaymentsString(h, payee));
- } else {
- doProjection = true;
- break;
- }
+ if (h <= nChainTipHeight) {
+ auto payee = deterministicMNManager->GetListForBlock(chainActive[h - 1]->GetBlockHash()).GetMNPayee();
+ mapPayments.emplace(h, GetRequiredPaymentsString(h, payee));
} else {
- mapPayments.emplace(h, GetLegacyRequiredPaymentsString(h));
+ doProjection = true;
+ break;
}
}
if (doProjection) {
@@ -327,33 +286,6 @@ std::map GetRequiredPaymentsStrings(int nStartHeight, int nEnd
return mapPayments;
}
-void CMasternodePayments::Clear()
-{
- LOCK2(cs_mapMasternodeBlocks, cs_mapMasternodePaymentVotes);
- mapMasternodeBlocks.clear();
- mapMasternodePaymentVotes.clear();
-}
-
-bool CMasternodePayments::UpdateLastVote(const CMasternodePaymentVote& vote)
-{
- if (deterministicMNManager->IsDeterministicMNsSporkActive())
- return false;
-
- LOCK(cs_mapMasternodePaymentVotes);
-
- const auto it = mapMasternodesLastVote.find(vote.masternodeOutpoint);
- if (it != mapMasternodesLastVote.end()) {
- if (it->second == vote.nBlockHeight)
- return false;
- it->second = vote.nBlockHeight;
- return true;
- }
-
- //record this masternode voted
- mapMasternodesLastVote.emplace(vote.masternodeOutpoint, vote.nBlockHeight);
- return true;
-}
-
/**
* GetMasternodeTxOuts
*
@@ -366,23 +298,8 @@ bool CMasternodePayments::GetMasternodeTxOuts(int nBlockHeight, CAmount blockRew
voutMasternodePaymentsRet.clear();
if(!GetBlockTxOuts(nBlockHeight, blockReward, voutMasternodePaymentsRet)) {
- if (deterministicMNManager->IsDeterministicMNsSporkActive(nBlockHeight)) {
- LogPrintf("CMasternodePayments::%s -- deterministic masternode lists enabled and no payee\n", __func__);
- return false;
- }
-
- // no masternode detected...
- int nCount = 0;
- masternode_info_t mnInfo;
- if(!mnodeman.GetNextMasternodeInQueueForPayment(nBlockHeight, true, nCount, mnInfo)) {
- // ...and we can't calculate it on our own
- LogPrintf("CMasternodePayments::%s -- Failed to detect masternode to pay\n", __func__);
- return false;
- }
- // fill payee with locally calculated winner and hope for the best
- CScript payee = GetScriptForDestination(mnInfo.keyIDCollateralAddress);
- CAmount masternodePayment = GetMasternodePayment(nBlockHeight, blockReward);
- voutMasternodePaymentsRet.emplace_back(masternodePayment, payee);
+ LogPrintf("CMasternodePayments::%s -- no payee (deterministic masternode list empty)\n", __func__);
+ return false;
}
for (const auto& txout : voutMasternodePaymentsRet) {
@@ -396,917 +313,77 @@ bool CMasternodePayments::GetMasternodeTxOuts(int nBlockHeight, CAmount blockRew
return true;
}
-int CMasternodePayments::GetMinMasternodePaymentsProto() const {
- return sporkManager.IsSporkActive(SPORK_10_MASTERNODE_PAY_UPDATED_NODES)
- ? MIN_MASTERNODE_PAYMENT_PROTO_VERSION_2
- : MIN_MASTERNODE_PAYMENT_PROTO_VERSION_1;
-}
-
-void CMasternodePayments::ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, CConnman& connman)
-{
- if (deterministicMNManager->IsDeterministicMNsSporkActive())
- return;
-
- if(fLiteMode) return; // disable all Dash specific functionality
-
- if (strCommand == NetMsgType::MASTERNODEPAYMENTSYNC) { //Masternode Payments Request Sync
-
- if(pfrom->nVersion < GetMinMasternodePaymentsProto()) {
- LogPrint("mnpayments", "MASTERNODEPAYMENTSYNC -- peer=%d using obsolete version %i\n", pfrom->id, pfrom->nVersion);
- connman.PushMessage(pfrom, CNetMsgMaker(pfrom->GetSendVersion()).Make(NetMsgType::REJECT, strCommand, REJECT_OBSOLETE,
- strprintf("Version must be %d or greater", GetMinMasternodePaymentsProto())));
- return;
- }
-
- // Ignore such requests until we are fully synced.
- // We could start processing this after masternode list is synced
- // but this is a heavy one so it's better to finish sync first.
- if (!masternodeSync.IsSynced()) return;
-
- if(netfulfilledman.HasFulfilledRequest(pfrom->addr, NetMsgType::MASTERNODEPAYMENTSYNC)) {
- LOCK(cs_main);
- // Asking for the payments list multiple times in a short period of time is no good
- LogPrintf("MASTERNODEPAYMENTSYNC -- peer already asked me for the list, peer=%d\n", pfrom->id);
- Misbehaving(pfrom->GetId(), 20);
- return;
- }
- netfulfilledman.AddFulfilledRequest(pfrom->addr, NetMsgType::MASTERNODEPAYMENTSYNC);
-
- Sync(pfrom, connman);
- LogPrintf("MASTERNODEPAYMENTSYNC -- Sent Masternode payment votes to peer=%d\n", pfrom->id);
-
- } else if (strCommand == NetMsgType::MASTERNODEPAYMENTVOTE) { // Masternode Payments Vote for the Winner
-
- CMasternodePaymentVote vote;
- vRecv >> vote;
-
- if(pfrom->nVersion < GetMinMasternodePaymentsProto()) {
- LogPrint("mnpayments", "MASTERNODEPAYMENTVOTE -- peer=%d using obsolete version %i\n", pfrom->id, pfrom->nVersion);
- connman.PushMessage(pfrom, CNetMsgMaker(pfrom->GetSendVersion()).Make(NetMsgType::REJECT, strCommand, REJECT_OBSOLETE,
- strprintf("Version must be %d or greater", GetMinMasternodePaymentsProto())));
- return;
- }
-
- uint256 nHash = vote.GetHash();
-
- {
- LOCK(cs_main);
- connman.RemoveAskFor(nHash);
- }
-
- // TODO: clear setAskFor for MSG_MASTERNODE_PAYMENT_BLOCK too
-
- // Ignore any payments messages until masternode list is synced
- if(!masternodeSync.IsMasternodeListSynced()) return;
-
- {
- LOCK(cs_mapMasternodePaymentVotes);
-
- auto res = mapMasternodePaymentVotes.emplace(nHash, vote);
-
- // Avoid processing same vote multiple times if it was already verified earlier
- if(!res.second && res.first->second.IsVerified()) {
- LogPrint("mnpayments", "MASTERNODEPAYMENTVOTE -- hash=%s, nBlockHeight=%d/%d seen\n",
- nHash.ToString(), vote.nBlockHeight, nCachedBlockHeight);
- return;
- }
-
- // Mark vote as non-verified when it's seen for the first time,
- // AddOrUpdatePaymentVote() below should take care of it if vote is actually ok
- res.first->second.MarkAsNotVerified();
- }
-
- int nFirstBlock = nCachedBlockHeight - GetStorageLimit();
- if(vote.nBlockHeight < nFirstBlock || vote.nBlockHeight > nCachedBlockHeight+20) {
- LogPrint("mnpayments", "MASTERNODEPAYMENTVOTE -- vote out of range: nFirstBlock=%d, nBlockHeight=%d, nHeight=%d\n", nFirstBlock, vote.nBlockHeight, nCachedBlockHeight);
- return;
- }
-
- std::string strError = "";
- if(!vote.IsValid(pfrom, nCachedBlockHeight, strError, connman)) {
- LogPrint("mnpayments", "MASTERNODEPAYMENTVOTE -- invalid message, error: %s\n", strError);
- return;
- }
-
- masternode_info_t mnInfo;
- if(!mnodeman.GetMasternodeInfo(vote.masternodeOutpoint, mnInfo)) {
- // mn was not found, so we can't check vote, some info is probably missing
- LogPrintf("MASTERNODEPAYMENTVOTE -- masternode is missing %s\n", vote.masternodeOutpoint.ToStringShort());
- mnodeman.AskForMN(pfrom, vote.masternodeOutpoint, connman);
- return;
- }
-
- int nDos = 0;
- if(!vote.CheckSignature(mnInfo.legacyKeyIDOperator, nCachedBlockHeight, nDos)) {
- if(nDos) {
- LOCK(cs_main);
- LogPrintf("MASTERNODEPAYMENTVOTE -- ERROR: invalid signature\n");
- Misbehaving(pfrom->GetId(), nDos);
- } else {
- // only warn about anything non-critical (i.e. nDos == 0) in debug mode
- LogPrint("mnpayments", "MASTERNODEPAYMENTVOTE -- WARNING: invalid signature\n");
- }
- // Either our info or vote info could be outdated.
- // In case our info is outdated, ask for an update,
- mnodeman.AskForMN(pfrom, vote.masternodeOutpoint, connman);
- // but there is nothing we can do if vote info itself is outdated
- // (i.e. it was signed by a mn which changed its key),
- // so just quit here.
- return;
- }
-
- if(!UpdateLastVote(vote)) {
- LogPrintf("MASTERNODEPAYMENTVOTE -- masternode already voted, masternode=%s\n", vote.masternodeOutpoint.ToStringShort());
- return;
- }
-
- CTxDestination address1;
- ExtractDestination(vote.payee, address1);
- CBitcoinAddress address2(address1);
-
- LogPrint("mnpayments", "MASTERNODEPAYMENTVOTE -- vote: address=%s, nBlockHeight=%d, nHeight=%d, prevout=%s, hash=%s new\n",
- address2.ToString(), vote.nBlockHeight, nCachedBlockHeight, vote.masternodeOutpoint.ToStringShort(), nHash.ToString());
-
- if(AddOrUpdatePaymentVote(vote)){
- vote.Relay(connman);
- masternodeSync.BumpAssetLastTime("MASTERNODEPAYMENTVOTE");
- }
- }
-}
-
-uint256 CMasternodePaymentVote::GetHash() const
-{
- // Note: doesn't match serialization
-
- CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
- ss << *(CScriptBase*)(&payee);
- ss << nBlockHeight;
- ss << masternodeOutpoint;
- return ss.GetHash();
-}
-
-uint256 CMasternodePaymentVote::GetSignatureHash() const
-{
- return SerializeHash(*this);
-}
-
-bool CMasternodePaymentVote::Sign()
-{
- std::string strError;
-
- if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
- uint256 hash = GetSignatureHash();
-
- if(!CHashSigner::SignHash(hash, activeMasternodeInfo.legacyKeyOperator, vchSig)) {
- LogPrintf("CMasternodePaymentVote::%s -- SignHash() failed\n", __func__);
- return false;
- }
-
- if (!CHashSigner::VerifyHash(hash, activeMasternodeInfo.legacyKeyIDOperator, vchSig, strError)) {
- LogPrintf("CMasternodePaymentVote::%s -- VerifyHash() failed, error: %s\n", __func__, strError);
- return false;
- }
- } else {
- std::string strMessage = masternodeOutpoint.ToStringShort() +
- std::to_string(nBlockHeight) +
- ScriptToAsmStr(payee);
-
- if(!CMessageSigner::SignMessage(strMessage, vchSig, activeMasternodeInfo.legacyKeyOperator)) {
- LogPrintf("CMasternodePaymentVote::%s -- SignMessage() failed\n", __func__);
- return false;
- }
-
- if(!CMessageSigner::VerifyMessage(activeMasternodeInfo.legacyKeyIDOperator, vchSig, strMessage, strError)) {
- LogPrintf("CMasternodePaymentVote::%s -- VerifyMessage() failed, error: %s\n", __func__, strError);
- return false;
- }
- }
-
- return true;
-}
-
bool CMasternodePayments::GetBlockTxOuts(int nBlockHeight, CAmount blockReward, std::vector& voutMasternodePaymentsRet) const
{
voutMasternodePaymentsRet.clear();
CAmount masternodeReward = GetMasternodePayment(nBlockHeight, blockReward);
- if (deterministicMNManager->IsDeterministicMNsSporkActive(nBlockHeight)) {
- uint256 blockHash;
- {
- LOCK(cs_main);
- if (nBlockHeight - 1 > chainActive.Height()) {
- // there are some cases (e.g. IsScheduled) where legacy/compatibility code runs into this method with
- // block heights above the chain tip. Return false in this case
- // TODO remove this when removing the compatibility code and make sure this method is only called with
- // correct block height
- return false;
- }
- blockHash = chainActive[nBlockHeight - 1]->GetBlockHash();
- }
- uint256 proTxHash;
- auto dmnPayee = deterministicMNManager->GetListForBlock(blockHash).GetMNPayee();
- if (!dmnPayee) {
- return false;
- }
-
- CAmount operatorReward = 0;
- if (dmnPayee->nOperatorReward != 0 && dmnPayee->pdmnState->scriptOperatorPayout != CScript()) {
- // This calculation might eventually turn out to result in 0 even if an operator reward percentage is given.
- // This will however only happen in a few years when the block rewards drops very low.
- operatorReward = (masternodeReward * dmnPayee->nOperatorReward) / 10000;
- masternodeReward -= operatorReward;
- }
-
- if (masternodeReward > 0) {
- voutMasternodePaymentsRet.emplace_back(masternodeReward, dmnPayee->pdmnState->scriptPayout);
- }
- if (operatorReward > 0) {
- voutMasternodePaymentsRet.emplace_back(operatorReward, dmnPayee->pdmnState->scriptOperatorPayout);
- }
-
- return true;
- } else {
- LOCK(cs_mapMasternodeBlocks);
- auto it = mapMasternodeBlocks.find(nBlockHeight);
- CScript payee;
- if (it == mapMasternodeBlocks.end() || !it->second.GetBestPayee(payee)) {
- return false;
- }
- voutMasternodePaymentsRet.emplace_back(masternodeReward, payee);
- return true;
- }
-}
-
-// Is this masternode scheduled to get paid soon?
-// -- Only look ahead up to 8 blocks to allow for propagation of the latest 2 blocks of votes
-bool CMasternodePayments::IsScheduled(const masternode_info_t& mnInfo, int nNotBlockHeight) const
-{
- LOCK(cs_mapMasternodeBlocks);
-
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
- auto projectedPayees = deterministicMNManager->GetListAtChainTip().GetProjectedMNPayees(8);
- for (const auto &dmn : projectedPayees) {
- if (dmn->collateralOutpoint == mnInfo.outpoint) {
- return true;
- }
- }
- return false;
- }
-
- if(!masternodeSync.IsMasternodeListSynced()) return false;
-
- CScript mnpayee;
- mnpayee = GetScriptForDestination(mnInfo.keyIDCollateralAddress);
-
- for(int64_t h = nCachedBlockHeight; h <= nCachedBlockHeight + 8; h++){
- if(h == nNotBlockHeight) continue;
- std::vector voutMasternodePayments;
- if(GetBlockTxOuts(h, 0, voutMasternodePayments)) {
- for (const auto& txout : voutMasternodePayments) {
- if (txout.scriptPubKey == mnpayee)
- return true;
- }
- }
- }
-
- return false;
-}
-
-bool CMasternodePayments::AddOrUpdatePaymentVote(const CMasternodePaymentVote& vote)
-{
- uint256 blockHash = uint256();
- if(!GetBlockHash(blockHash, vote.nBlockHeight - 101)) return false;
-
- uint256 nVoteHash = vote.GetHash();
-
- if(HasVerifiedPaymentVote(nVoteHash)) return false;
-
- LOCK2(cs_mapMasternodeBlocks, cs_mapMasternodePaymentVotes);
-
- mapMasternodePaymentVotes[nVoteHash] = vote;
-
- auto it = mapMasternodeBlocks.emplace(vote.nBlockHeight, CMasternodeBlockPayees(vote.nBlockHeight)).first;
- it->second.AddPayee(vote);
-
- LogPrint("mnpayments", "CMasternodePayments::%s -- added, hash=%s\n", __func__, nVoteHash.ToString());
-
- return true;
-}
-
-bool CMasternodePayments::HasVerifiedPaymentVote(const uint256& hashIn) const
-{
- LOCK(cs_mapMasternodePaymentVotes);
- const auto it = mapMasternodePaymentVotes.find(hashIn);
- return it != mapMasternodePaymentVotes.end() && it->second.IsVerified();
-}
-
-void CMasternodeBlockPayees::AddPayee(const CMasternodePaymentVote& vote)
-{
- LOCK(cs_vecPayees);
-
- uint256 nVoteHash = vote.GetHash();
-
- for (auto& payee : vecPayees) {
- if (payee.GetPayee() == vote.payee) {
- payee.AddVoteHash(nVoteHash);
- return;
- }
- }
- CMasternodePayee payeeNew(vote.payee, nVoteHash);
- vecPayees.push_back(payeeNew);
-}
-
-bool CMasternodeBlockPayees::GetBestPayee(CScript& payeeRet) const
-{
- LOCK(cs_vecPayees);
-
- if(vecPayees.empty()) {
- LogPrint("mnpayments", "CMasternodeBlockPayees::%s -- ERROR: couldn't find any payee\n", __func__);
- return false;
- }
-
- int nVotes = -1;
- for (const auto& payee : vecPayees) {
- if (payee.GetVoteCount() > nVotes) {
- payeeRet = payee.GetPayee();
- nVotes = payee.GetVoteCount();
- }
- }
-
- return (nVotes > -1);
-}
-
-bool CMasternodeBlockPayees::HasPayeeWithVotes(const CScript& payeeIn, int nVotesReq) const
-{
- LOCK(cs_vecPayees);
-
- for (const auto& payee : vecPayees) {
- if (payee.GetVoteCount() >= nVotesReq && payee.GetPayee() == payeeIn) {
- return true;
- }
- }
-
- LogPrint("mnpayments", "CMasternodeBlockPayees::%s -- ERROR: couldn't find any payee with %d+ votes\n", __func__, nVotesReq);
- return false;
-}
-
-bool CMasternodeBlockPayees::IsTransactionValid(const CTransaction& txNew) const
-{
- LOCK(cs_vecPayees);
-
- int nMaxSignatures = 0;
- std::string strPayeesPossible = "";
-
- CAmount nMasternodePayment = GetMasternodePayment(nBlockHeight, txNew.GetValueOut());
-
- //require at least MNPAYMENTS_SIGNATURES_REQUIRED signatures
-
- for (const auto& payee : vecPayees) {
- if (payee.GetVoteCount() >= nMaxSignatures) {
- nMaxSignatures = payee.GetVoteCount();
- }
- }
-
- // if we don't have at least MNPAYMENTS_SIGNATURES_REQUIRED signatures on a payee, approve whichever is the longest chain
- if(nMaxSignatures < MNPAYMENTS_SIGNATURES_REQUIRED) return true;
-
- for (const auto& payee : vecPayees) {
- if (payee.GetVoteCount() >= MNPAYMENTS_SIGNATURES_REQUIRED) {
- for (const auto& txout : txNew.vout) {
- if (payee.GetPayee() == txout.scriptPubKey && nMasternodePayment == txout.nValue) {
- LogPrint("mnpayments", "CMasternodeBlockPayees::%s -- Found required payment\n", __func__);
- return true;
- }
- }
-
- CTxDestination address1;
- ExtractDestination(payee.GetPayee(), address1);
- CBitcoinAddress address2(address1);
-
- if(strPayeesPossible == "") {
- strPayeesPossible = address2.ToString();
- } else {
- strPayeesPossible += "," + address2.ToString();
- }
- }
- }
-
- LogPrintf("CMasternodeBlockPayees::%s -- ERROR: Missing required payment, possible payees: '%s', amount: %f DASH\n", __func__, strPayeesPossible, (float)nMasternodePayment/COIN);
- return false;
-}
-
-std::string CMasternodeBlockPayees::GetRequiredPaymentsString() const
-{
- LOCK(cs_vecPayees);
-
- std::string strRequiredPayments = "";
-
- for (const auto& payee : vecPayees)
+ uint256 blockHash;
{
- CTxDestination address1;
- ExtractDestination(payee.GetPayee(), address1);
- CBitcoinAddress address2(address1);
-
- if (!strRequiredPayments.empty())
- strRequiredPayments += ", ";
-
- strRequiredPayments += strprintf("%s:%d", address2.ToString(), payee.GetVoteCount());
- }
-
- if (strRequiredPayments.empty())
- return "Unknown";
-
- return strRequiredPayments;
-}
-
-std::string CMasternodePayments::GetRequiredPaymentsString(int nBlockHeight) const
-{
- LOCK(cs_mapMasternodeBlocks);
- const auto it = mapMasternodeBlocks.find(nBlockHeight);
- return it == mapMasternodeBlocks.end() ? "Unknown" : it->second.GetRequiredPaymentsString();
-}
-
-bool CMasternodePayments::IsTransactionValid(const CTransaction& txNew, int nBlockHeight, CAmount blockReward) const
-{
- if (deterministicMNManager->IsDeterministicMNsSporkActive(nBlockHeight)) {
- std::vector voutMasternodePayments;
- if (!GetBlockTxOuts(nBlockHeight, blockReward, voutMasternodePayments)) {
- LogPrintf("CMasternodePayments::%s -- ERROR failed to get payees for block at height %s\n", __func__, nBlockHeight);
- return true;
- }
-
- for (const auto& txout : voutMasternodePayments) {
- bool found = false;
- for (const auto& txout2 : txNew.vout) {
- if (txout == txout2) {
- found = true;
- break;
- }
- }
- if (!found) {
- CTxDestination dest;
- if (!ExtractDestination(txout.scriptPubKey, dest))
- assert(false);
- LogPrintf("CMasternodePayments::%s -- ERROR failed to find expected payee %s in block at height %s\n", __func__, CBitcoinAddress(dest).ToString(), nBlockHeight);
- return false;
- }
- }
- return true;
- } else {
- LOCK(cs_mapMasternodeBlocks);
- const auto it = mapMasternodeBlocks.find(nBlockHeight);
- return it == mapMasternodeBlocks.end() ? true : it->second.IsTransactionValid(txNew);
- }
-}
-
-void CMasternodePayments::CheckAndRemove()
-{
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
- return;
+ LOCK(cs_main);
+ blockHash = chainActive[nBlockHeight - 1]->GetBlockHash();
}
-
- if(!masternodeSync.IsBlockchainSynced()) return;
-
- LOCK2(cs_mapMasternodeBlocks, cs_mapMasternodePaymentVotes);
-
- int nLimit = GetStorageLimit();
-
- std::map::iterator it = mapMasternodePaymentVotes.begin();
- while(it != mapMasternodePaymentVotes.end()) {
- CMasternodePaymentVote vote = (*it).second;
-
- if(nCachedBlockHeight - vote.nBlockHeight > nLimit) {
- LogPrint("mnpayments", "CMasternodePayments::%s -- Removing old Masternode payment: nBlockHeight=%d\n", __func__, vote.nBlockHeight);
- mapMasternodePaymentVotes.erase(it++);
- mapMasternodeBlocks.erase(vote.nBlockHeight);
- } else {
- ++it;
- }
- }
- LogPrintf("CMasternodePayments::%s -- %s\n", __func__, ToString());
-}
-
-bool CMasternodePaymentVote::IsValid(CNode* pnode, int nValidationHeight, std::string& strError, CConnman& connman) const
-{
- masternode_info_t mnInfo;
-
- if(!mnodeman.GetMasternodeInfo(masternodeOutpoint, mnInfo)) {
- strError = strprintf("Unknown masternode=%s", masternodeOutpoint.ToStringShort());
- // Only ask if we are already synced and still have no idea about that Masternode
- if(masternodeSync.IsMasternodeListSynced()) {
- mnodeman.AskForMN(pnode, masternodeOutpoint, connman);
- }
-
+ uint256 proTxHash;
+ auto dmnPayee = deterministicMNManager->GetListForBlock(blockHash).GetMNPayee();
+ if (!dmnPayee) {
return false;
}
- int nMinRequiredProtocol;
- if(nBlockHeight >= nValidationHeight) {
- // new votes must comply SPORK_10_MASTERNODE_PAY_UPDATED_NODES rules
- nMinRequiredProtocol = mnpayments.GetMinMasternodePaymentsProto();
- } else {
- // allow non-updated masternodes for old blocks
- nMinRequiredProtocol = MIN_MASTERNODE_PAYMENT_PROTO_VERSION_1;
+ CAmount operatorReward = 0;
+ if (dmnPayee->nOperatorReward != 0 && dmnPayee->pdmnState->scriptOperatorPayout != CScript()) {
+ // This calculation might eventually turn out to result in 0 even if an operator reward percentage is given.
+ // This will however only happen in a few years when the block rewards drops very low.
+ operatorReward = (masternodeReward * dmnPayee->nOperatorReward) / 10000;
+ masternodeReward -= operatorReward;
}
- if(mnInfo.nProtocolVersion < nMinRequiredProtocol) {
- strError = strprintf("Masternode protocol is too old: nProtocolVersion=%d, nMinRequiredProtocol=%d", mnInfo.nProtocolVersion, nMinRequiredProtocol);
- return false;
+ if (masternodeReward > 0) {
+ voutMasternodePaymentsRet.emplace_back(masternodeReward, dmnPayee->pdmnState->scriptPayout);
}
-
- // Only masternodes should try to check masternode rank for old votes - they need to pick the right winner for future blocks.
- // Regular clients (miners included) need to verify masternode rank for future block votes only.
- if(!fMasternodeMode && nBlockHeight < nValidationHeight) return true;
-
- int nRank;
-
- if(!mnodeman.GetMasternodeRank(masternodeOutpoint, nRank, nBlockHeight - 101, nMinRequiredProtocol)) {
- LogPrint("mnpayments", "CMasternodePaymentVote::%s -- Can't calculate rank for masternode %s\n", __func__,
- masternodeOutpoint.ToStringShort());
- return false;
- }
-
- if(nRank > MNPAYMENTS_SIGNATURES_TOTAL) {
- // It's common to have masternodes mistakenly think they are in the top 10
- // We don't want to print all of these messages in normal mode, debug mode should print though
- strError = strprintf("Masternode %s is not in the top %d (%d)", masternodeOutpoint.ToStringShort(), MNPAYMENTS_SIGNATURES_TOTAL, nRank);
- // Only ban for new mnw which is out of bounds, for old mnw MN list itself might be way too much off
- if(nRank > MNPAYMENTS_SIGNATURES_TOTAL*2 && nBlockHeight > nValidationHeight) {
- LOCK(cs_main);
- strError = strprintf("Masternode %s is not in the top %d (%d)", masternodeOutpoint.ToStringShort(), MNPAYMENTS_SIGNATURES_TOTAL*2, nRank);
- LogPrintf("CMasternodePaymentVote::%s -- Error: %s\n", __func__, strError);
- Misbehaving(pnode->GetId(), 20);
- }
- // Still invalid however
- return false;
+ if (operatorReward > 0) {
+ voutMasternodePaymentsRet.emplace_back(operatorReward, dmnPayee->pdmnState->scriptOperatorPayout);
}
return true;
}
-bool CMasternodePayments::ProcessBlock(int nBlockHeight, CConnman& connman)
+// Is this masternode scheduled to get paid soon?
+// -- Only look ahead up to 8 blocks to allow for propagation of the latest 2 blocks of votes
+bool CMasternodePayments::IsScheduled(const CDeterministicMNCPtr& dmnIn, int nNotBlockHeight) const
{
- if (deterministicMNManager->IsDeterministicMNsSporkActive(nBlockHeight)) {
- return true;
- }
-
- // DETERMINE IF WE SHOULD BE VOTING FOR THE NEXT PAYEE
-
- if(fLiteMode || !fMasternodeMode) return false;
-
- // We have little chances to pick the right winner if winners list is out of sync
- // but we have no choice, so we'll try. However it doesn't make sense to even try to do so
- // if we have not enough data about masternodes.
- if(!masternodeSync.IsMasternodeListSynced()) return false;
-
- int nRank;
-
- if (!mnodeman.GetMasternodeRank(activeMasternodeInfo.outpoint, nRank, nBlockHeight - 101, GetMinMasternodePaymentsProto())) {
- LogPrint("mnpayments", "CMasternodePayments::%s -- Unknown Masternode\n", __func__);
- return false;
- }
-
- if (nRank > MNPAYMENTS_SIGNATURES_TOTAL) {
- LogPrint("mnpayments", "CMasternodePayments::%s -- Masternode not in the top %d (%d)\n", __func__, MNPAYMENTS_SIGNATURES_TOTAL, nRank);
- return false;
- }
-
-
- // LOCATE THE NEXT MASTERNODE WHICH SHOULD BE PAID
-
- LogPrintf("CMasternodePayments::%s -- Start: nBlockHeight=%d, masternode=%s\n", __func__, nBlockHeight, activeMasternodeInfo.outpoint.ToStringShort());
-
- // pay to the oldest MN that still had no payment but its input is old enough and it was active long enough
- int nCount = 0;
- masternode_info_t mnInfo;
-
- if (!mnodeman.GetNextMasternodeInQueueForPayment(nBlockHeight, true, nCount, mnInfo)) {
- LogPrintf("CMasternodePayments::%s -- ERROR: Failed to find masternode to pay\n", __func__);
- return false;
- }
-
- LogPrintf("CMasternodePayments::%s -- Masternode found by GetNextMasternodeInQueueForPayment(): %s\n", __func__, mnInfo.outpoint.ToStringShort());
-
-
- CScript payee = GetScriptForDestination(mnInfo.keyIDCollateralAddress);
-
- CMasternodePaymentVote voteNew(activeMasternodeInfo.outpoint, nBlockHeight, payee);
-
- CTxDestination address1;
- ExtractDestination(payee, address1);
- CBitcoinAddress address2(address1);
-
- LogPrintf("CMasternodePayments::%s -- vote: payee=%s, nBlockHeight=%d\n", __func__, address2.ToString(), nBlockHeight);
-
- // SIGN MESSAGE TO NETWORK WITH OUR MASTERNODE KEYS
-
- LogPrintf("CMasternodePayments::%s -- Signing vote\n", __func__);
- if (voteNew.Sign()) {
- LogPrintf("CMasternodePayments::%s -- AddOrUpdatePaymentVote()\n", __func__);
-
- if (AddOrUpdatePaymentVote(voteNew)) {
- voteNew.Relay(connman);
+ auto projectedPayees = deterministicMNManager->GetListAtChainTip().GetProjectedMNPayees(8);
+ for (const auto &dmn : projectedPayees) {
+ if (dmn->proTxHash == dmnIn->proTxHash) {
return true;
}
}
-
return false;
}
-void CMasternodePayments::CheckBlockVotes(int nBlockHeight)
+bool CMasternodePayments::IsTransactionValid(const CTransaction& txNew, int nBlockHeight, CAmount blockReward) const
{
- if (!masternodeSync.IsWinnersListSynced()) return;
-
- CMasternodeMan::rank_pair_vec_t mns;
- if (!mnodeman.GetMasternodeRanks(mns, nBlockHeight - 101, GetMinMasternodePaymentsProto())) {
- LogPrintf("CMasternodePayments::%s -- nBlockHeight=%d, GetMasternodeRanks failed\n", __func__, nBlockHeight);
- return;
+ std::vector voutMasternodePayments;
+ if (!GetBlockTxOuts(nBlockHeight, blockReward, voutMasternodePayments)) {
+ LogPrintf("CMasternodePayments::%s -- ERROR failed to get payees for block at height %s\n", __func__, nBlockHeight);
+ return true;
}
- std::string debugStr;
-
- debugStr += strprintf("CMasternodePayments::%s -- nBlockHeight=%d,\n Expected voting MNs:\n", __func__, nBlockHeight);
-
- LOCK2(cs_mapMasternodeBlocks, cs_mapMasternodePaymentVotes);
-
- int i{0};
- for (const auto& mn : mns) {
- CScript payee;
+ for (const auto& txout : voutMasternodePayments) {
bool found = false;
-
- const auto it = mapMasternodeBlocks.find(nBlockHeight);
- if (it != mapMasternodeBlocks.end()) {
- for (const auto& p : it->second.vecPayees) {
- for (const auto& voteHash : p.GetVoteHashes()) {
- const auto itVote = mapMasternodePaymentVotes.find(voteHash);
- if (itVote == mapMasternodePaymentVotes.end()) {
- debugStr += strprintf(" - could not find vote %s\n",
- voteHash.ToString());
- continue;
- }
- if (itVote->second.masternodeOutpoint == mn.second.outpoint) {
- payee = itVote->second.payee;
- found = true;
- break;
- }
- }
- }
- }
-
- if (found) {
- CTxDestination address1;
- ExtractDestination(payee, address1);
- CBitcoinAddress address2(address1);
-
- debugStr += strprintf(" - %s - voted for %s\n",
- mn.second.outpoint.ToStringShort(), address2.ToString());
- } else {
- mapMasternodesDidNotVote.emplace(mn.second.outpoint, 0).first->second++;
-
- debugStr += strprintf(" - %s - no vote received\n",
- mn.second.outpoint.ToStringShort());
- }
-
- if (++i >= MNPAYMENTS_SIGNATURES_TOTAL) break;
- }
-
- if (mapMasternodesDidNotVote.empty()) {
- LogPrint("mnpayments", "%s", debugStr);
- return;
- }
-
- debugStr += " Masternodes which missed a vote in the past:\n";
- for (const auto& item : mapMasternodesDidNotVote) {
- debugStr += strprintf(" - %s: %d\n", item.first.ToStringShort(), item.second);
- }
-
- LogPrint("mnpayments", "%s", debugStr);
-}
-
-void CMasternodePaymentVote::Relay(CConnman& connman) const
-{
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
- return;
- }
-
- // Do not relay until fully synced
- if(!masternodeSync.IsSynced()) {
- LogPrint("mnpayments", "CMasternodePayments::%s -- won't relay until fully synced\n", __func__);
- return;
- }
-
- CInv inv(MSG_MASTERNODE_PAYMENT_VOTE, GetHash());
- connman.RelayInv(inv);
-}
-
-bool CMasternodePaymentVote::CheckSignature(const CKeyID& keyIDOperator, int nValidationHeight, int &nDos) const
-{
- // do not ban by default
- nDos = 0;
- std::string strError = "";
-
- if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
- uint256 hash = GetSignatureHash();
-
- if (!CHashSigner::VerifyHash(hash, keyIDOperator, vchSig, strError)) {
- // could be a signature in old format
- std::string strMessage = masternodeOutpoint.ToStringShort() +
- std::to_string(nBlockHeight) +
- ScriptToAsmStr(payee);
- if(!CMessageSigner::VerifyMessage(keyIDOperator, vchSig, strMessage, strError)) {
- // nope, not in old format either
- // Only ban for future block vote when we are already synced.
- // Otherwise it could be the case when MN which signed this vote is using another key now
- // and we have no idea about the old one.
- if(masternodeSync.IsMasternodeListSynced() && nBlockHeight > nValidationHeight) {
- nDos = 20;
- }
- return error("CMasternodePaymentVote::CheckSignature -- Got bad Masternode payment signature, masternode=%s, error: %s",
- masternodeOutpoint.ToStringShort(), strError);
- }
- }
- } else {
- std::string strMessage = masternodeOutpoint.ToStringShort() +
- std::to_string(nBlockHeight) +
- ScriptToAsmStr(payee);
-
- if (!CMessageSigner::VerifyMessage(keyIDOperator, vchSig, strMessage, strError)) {
- // Only ban for future block vote when we are already synced.
- // Otherwise it could be the case when MN which signed this vote is using another key now
- // and we have no idea about the old one.
- if(masternodeSync.IsMasternodeListSynced() && nBlockHeight > nValidationHeight) {
- nDos = 20;
- }
- return error("CMasternodePaymentVote::CheckSignature -- Got bad Masternode payment signature, masternode=%s, error: %s",
- masternodeOutpoint.ToStringShort(), strError);
- }
- }
-
- return true;
-}
-
-std::string CMasternodePaymentVote::ToString() const
-{
- std::ostringstream info;
-
- info << masternodeOutpoint.ToStringShort() <<
- ", " << nBlockHeight <<
- ", " << ScriptToAsmStr(payee) <<
- ", " << (int)vchSig.size();
-
- return info.str();
-}
-
-// Send only votes for future blocks, node should request every other missing payment block individually
-void CMasternodePayments::Sync(CNode* pnode, CConnman& connman) const
-{
- LOCK(cs_mapMasternodeBlocks);
-
- if(!masternodeSync.IsWinnersListSynced()) return;
-
- int nInvCount = 0;
-
- for(int h = nCachedBlockHeight; h < nCachedBlockHeight + 20; h++) {
- const auto it = mapMasternodeBlocks.find(h);
- if(it != mapMasternodeBlocks.end()) {
- for (const auto& payee : it->second.vecPayees) {
- std::vector vecVoteHashes = payee.GetVoteHashes();
- for (const auto& hash : vecVoteHashes) {
- if(!HasVerifiedPaymentVote(hash)) continue;
- pnode->PushInventory(CInv(MSG_MASTERNODE_PAYMENT_VOTE, hash));
- nInvCount++;
- }
- }
- }
- }
-
- LogPrintf("CMasternodePayments::%s -- Sent %d votes to peer=%d\n", __func__, nInvCount, pnode->id);
- CNetMsgMaker msgMaker(pnode->GetSendVersion());
- connman.PushMessage(pnode, msgMaker.Make(NetMsgType::SYNCSTATUSCOUNT, MASTERNODE_SYNC_MNW, nInvCount));
-}
-
-// Request low data/unknown payment blocks in batches directly from some node instead of/after preliminary Sync.
-void CMasternodePayments::RequestLowDataPaymentBlocks(CNode* pnode, CConnman& connman) const
-{
- if(!masternodeSync.IsMasternodeListSynced()) return;
-
- CNetMsgMaker msgMaker(pnode->GetSendVersion());
- LOCK2(cs_main, cs_mapMasternodeBlocks);
-
- std::vector vToFetch;
- int nLimit = GetStorageLimit();
-
- const CBlockIndex *pindex = chainActive.Tip();
-
- while(nCachedBlockHeight - pindex->nHeight < nLimit) {
- const auto it = mapMasternodeBlocks.find(pindex->nHeight);
- if(it == mapMasternodeBlocks.end()) {
- // We have no idea about this block height, let's ask
- vToFetch.push_back(CInv(MSG_MASTERNODE_PAYMENT_BLOCK, pindex->GetBlockHash()));
- // We should not violate GETDATA rules
- if(vToFetch.size() == MAX_INV_SZ) {
- LogPrintf("CMasternodePayments::%s -- asking peer=%d for %d blocks\n", __func__, pnode->id, MAX_INV_SZ);
- connman.PushMessage(pnode, msgMaker.Make(NetMsgType::GETDATA, vToFetch));
- // Start filling new batch
- vToFetch.clear();
- }
- }
- if(!pindex->pprev) break;
- pindex = pindex->pprev;
- }
-
- for (auto& mnBlockPayees : mapMasternodeBlocks) {
- int nBlockHeight = mnBlockPayees.first;
- int nTotalVotes = 0;
- bool fFound = false;
- for (const auto& payee : mnBlockPayees.second.vecPayees) {
- if(payee.GetVoteCount() >= MNPAYMENTS_SIGNATURES_REQUIRED) {
- fFound = true;
+ for (const auto& txout2 : txNew.vout) {
+ if (txout == txout2) {
+ found = true;
break;
}
- nTotalVotes += payee.GetVoteCount();
- }
- // A clear winner (MNPAYMENTS_SIGNATURES_REQUIRED+ votes) was found
- // or no clear winner was found but there are at least avg number of votes
- if(fFound || nTotalVotes >= (MNPAYMENTS_SIGNATURES_TOTAL + MNPAYMENTS_SIGNATURES_REQUIRED)/2) {
- // so just move to the next block
- continue;
- }
- // DEBUG
- DBG (
- // Let's see why this failed
- for (const auto& payee : mnBlockPayees.second.vecPayees) {
- CTxDestination address1;
- ExtractDestination(payee.GetPayee(), address1);
- CBitcoinAddress address2(address1);
- printf("payee %s votes %d\n", address2.ToString().c_str(), payee.GetVoteCount());
- }
- printf("block %d votes total %d\n", nBlockHeight, nTotalVotes);
- )
- // END DEBUG
- // Low data block found, let's try to sync it
- uint256 hash;
- if(GetBlockHash(hash, nBlockHeight)) {
- vToFetch.push_back(CInv(MSG_MASTERNODE_PAYMENT_BLOCK, hash));
}
- // We should not violate GETDATA rules
- if(vToFetch.size() == MAX_INV_SZ) {
- LogPrintf("CMasternodePayments::%s -- asking peer=%d for %d payment blocks\n", __func__, pnode->id, MAX_INV_SZ);
- connman.PushMessage(pnode, msgMaker.Make(NetMsgType::GETDATA, vToFetch));
- // Start filling new batch
- vToFetch.clear();
+ if (!found) {
+ CTxDestination dest;
+ if (!ExtractDestination(txout.scriptPubKey, dest))
+ assert(false);
+ LogPrintf("CMasternodePayments::%s -- ERROR failed to find expected payee %s in block at height %s\n", __func__, CBitcoinAddress(dest).ToString(), nBlockHeight);
+ return false;
}
}
- // Ask for the rest of it
- if(!vToFetch.empty()) {
- LogPrintf("CMasternodePayments::%s -- asking peer=%d for %d payment blocks\n", __func__, pnode->id, vToFetch.size());
- connman.PushMessage(pnode, msgMaker.Make(NetMsgType::GETDATA, vToFetch));
- }
-}
-
-std::string CMasternodePayments::ToString() const
-{
- std::ostringstream info;
-
- info << "Votes: " << (int)mapMasternodePaymentVotes.size() <<
- ", Blocks: " << (int)mapMasternodeBlocks.size();
-
- return info.str();
-}
-
-bool CMasternodePayments::IsEnoughData() const
-{
- float nAverageVotes = (MNPAYMENTS_SIGNATURES_TOTAL + MNPAYMENTS_SIGNATURES_REQUIRED) / 2;
- int nStorageLimit = GetStorageLimit();
- return GetBlockCount() > nStorageLimit && GetVoteCount() > nStorageLimit * nAverageVotes;
-}
-
-int CMasternodePayments::GetStorageLimit() const
-{
- return std::max(int(mnodeman.size() * nStorageCoeff), nMinBlocksToStore);
-}
-
-void CMasternodePayments::UpdatedBlockTip(const CBlockIndex *pindex, CConnman& connman)
-{
- if(!pindex) return;
-
- if (deterministicMNManager->IsDeterministicMNsSporkActive(pindex->nHeight)) {
- return;
- }
-
- nCachedBlockHeight = pindex->nHeight;
- LogPrint("mnpayments", "CMasternodePayments::%s -- nCachedBlockHeight=%d\n", __func__, nCachedBlockHeight);
-
- int nFutureBlock = nCachedBlockHeight + 10;
-
- CheckBlockVotes(nFutureBlock - 1);
- ProcessBlock(nFutureBlock, connman);
-}
-
-void CMasternodePayments::DoMaintenance()
-{
- if (ShutdownRequested()) return;
-
- CheckAndRemove();
+ return true;
}
diff --git a/src/masternode-payments.h b/src/masternode-payments.h
index 984551c923f4..b50ea0e4d5ab 100644
--- a/src/masternode-payments.h
+++ b/src/masternode-payments.h
@@ -8,28 +8,12 @@
#include "util.h"
#include "core_io.h"
#include "key.h"
-#include "masternode.h"
#include "net_processing.h"
#include "utilstrencodings.h"
-class CMasternodePayments;
-class CMasternodePaymentVote;
-class CMasternodeBlockPayees;
-
-static const int MNPAYMENTS_SIGNATURES_REQUIRED = 6;
-static const int MNPAYMENTS_SIGNATURES_TOTAL = 10;
-
-//! minimum peer version that can receive and send masternode payment messages,
-// vote for masternode and be elected as a payment winner
-// V1 - Last protocol version before update
-// V2 - Newest protocol version
-static const int MIN_MASTERNODE_PAYMENT_PROTO_VERSION_1 = 70210;
-static const int MIN_MASTERNODE_PAYMENT_PROTO_VERSION_2 = 70210;
-
-extern CCriticalSection cs_vecPayees;
-extern CCriticalSection cs_mapMasternodeBlocks;
+#include "evo/deterministicmns.h"
-extern CMasternodePayments mnpayments;
+class CMasternodePayments;
/// TODO: all 4 functions do not belong here really, they should be refactored/moved somewhere (main.cpp ?)
bool IsBlockValueValid(const CBlock& block, int nBlockHeight, CAmount blockReward, std::string& strErrorRet);
@@ -37,123 +21,7 @@ bool IsBlockPayeeValid(const CTransaction& txNew, int nBlockHeight, CAmount bloc
void FillBlockPayments(CMutableTransaction& txNew, int nBlockHeight, CAmount blockReward, std::vector& voutMasternodePaymentsRet, std::vector& voutSuperblockPaymentsRet);
std::map GetRequiredPaymentsStrings(int nStartHeight, int nEndHeight);
-class CMasternodePayee
-{
-private:
- CScript scriptPubKey;
- std::vector vecVoteHashes;
-
-public:
- CMasternodePayee() :
- scriptPubKey(),
- vecVoteHashes()
- {}
-
- CMasternodePayee(CScript payee, uint256 hashIn) :
- scriptPubKey(payee),
- vecVoteHashes()
- {
- vecVoteHashes.push_back(hashIn);
- }
-
- ADD_SERIALIZE_METHODS;
-
- template
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(*(CScriptBase*)(&scriptPubKey));
- READWRITE(vecVoteHashes);
- }
-
- CScript GetPayee() const { return scriptPubKey; }
-
- void AddVoteHash(uint256 hashIn) { vecVoteHashes.push_back(hashIn); }
- std::vector GetVoteHashes() const { return vecVoteHashes; }
- int GetVoteCount() const { return vecVoteHashes.size(); }
-};
-
-// Keep track of votes for payees from masternodes
-class CMasternodeBlockPayees
-{
-public:
- int nBlockHeight;
- std::vector vecPayees;
-
- CMasternodeBlockPayees() :
- nBlockHeight(0),
- vecPayees()
- {}
- CMasternodeBlockPayees(int nBlockHeightIn) :
- nBlockHeight(nBlockHeightIn),
- vecPayees()
- {}
-
- ADD_SERIALIZE_METHODS;
-
- template
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(nBlockHeight);
- READWRITE(vecPayees);
- }
-
- void AddPayee(const CMasternodePaymentVote& vote);
- bool GetBestPayee(CScript& payeeRet) const;
- bool HasPayeeWithVotes(const CScript& payeeIn, int nVotesReq) const;
-
- bool IsTransactionValid(const CTransaction& txNew) const;
-
- std::string GetRequiredPaymentsString() const;
-};
-
-// vote for the winning payment
-class CMasternodePaymentVote
-{
-public:
- COutPoint masternodeOutpoint;
-
- int nBlockHeight;
- CScript payee;
- std::vector vchSig;
-
- CMasternodePaymentVote() :
- masternodeOutpoint(),
- nBlockHeight(0),
- payee(),
- vchSig()
- {}
-
- CMasternodePaymentVote(COutPoint outpoint, int nBlockHeight, CScript payee) :
- masternodeOutpoint(outpoint),
- nBlockHeight(nBlockHeight),
- payee(payee),
- vchSig()
- {}
-
- ADD_SERIALIZE_METHODS;
-
- template
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(masternodeOutpoint);
- READWRITE(nBlockHeight);
- READWRITE(*(CScriptBase*)(&payee));
- if (!(s.GetType() & SER_GETHASH)) {
- READWRITE(vchSig);
- }
- }
-
- uint256 GetHash() const;
- uint256 GetSignatureHash() const;
-
- bool Sign();
- bool CheckSignature(const CKeyID& keyIDOperator, int nValidationHeight, int &nDos) const;
-
- bool IsValid(CNode* pnode, int nValidationHeight, std::string& strError, CConnman& connman) const;
- void Relay(CConnman& connman) const;
-
- bool IsVerified() const { return !vchSig.empty(); }
- void MarkAsNotVerified() { vchSig.clear(); }
-
- std::string ToString() const;
-};
+extern CMasternodePayments mnpayments;
//
// Masternode Payments Class
@@ -162,63 +30,12 @@ class CMasternodePaymentVote
class CMasternodePayments
{
-private:
- // masternode count times nStorageCoeff payments blocks should be stored ...
- const float nStorageCoeff;
- // ... but at least nMinBlocksToStore (payments blocks)
- const int nMinBlocksToStore;
-
- // Keep track of current block height
- int nCachedBlockHeight;
-
public:
- std::map mapMasternodePaymentVotes;
- std::map mapMasternodeBlocks;
- std::map mapMasternodesLastVote;
- std::map mapMasternodesDidNotVote;
-
- CMasternodePayments() : nStorageCoeff(1.25), nMinBlocksToStore(6000) {}
-
- ADD_SERIALIZE_METHODS;
-
- template
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(mapMasternodePaymentVotes);
- READWRITE(mapMasternodeBlocks);
- }
-
- void Clear();
-
- bool AddOrUpdatePaymentVote(const CMasternodePaymentVote& vote);
- bool HasVerifiedPaymentVote(const uint256& hashIn) const;
- bool ProcessBlock(int nBlockHeight, CConnman& connman);
- void CheckBlockVotes(int nBlockHeight);
-
- void Sync(CNode* node, CConnman& connman) const;
- void RequestLowDataPaymentBlocks(CNode* pnode, CConnman& connman) const;
- void CheckAndRemove();
-
bool GetBlockTxOuts(int nBlockHeight, CAmount blockReward, std::vector& voutMasternodePaymentsRet) const;
bool IsTransactionValid(const CTransaction& txNew, int nBlockHeight, CAmount blockReward) const;
- bool IsScheduled(const masternode_info_t& mnInfo, int nNotBlockHeight) const;
-
- bool UpdateLastVote(const CMasternodePaymentVote& vote);
+ bool IsScheduled(const CDeterministicMNCPtr& dmn, int nNotBlockHeight) const;
- int GetMinMasternodePaymentsProto() const;
- void ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, CConnman& connman);
- std::string GetRequiredPaymentsString(int nBlockHeight) const;
bool GetMasternodeTxOuts(int nBlockHeight, CAmount blockReward, std::vector& voutMasternodePaymentsRet) const;
- std::string ToString() const;
-
- int GetBlockCount() const { return mapMasternodeBlocks.size(); }
- int GetVoteCount() const { return mapMasternodePaymentVotes.size(); }
-
- bool IsEnoughData() const;
- int GetStorageLimit() const;
-
- void UpdatedBlockTip(const CBlockIndex *pindex, CConnman& connman);
-
- void DoMaintenance();
};
#endif
diff --git a/src/masternode-sync.cpp b/src/masternode-sync.cpp
index b5cf4dc950fe..1cc316408089 100644
--- a/src/masternode-sync.cpp
+++ b/src/masternode-sync.cpp
@@ -8,7 +8,6 @@
#include "validation.h"
#include "masternode-payments.h"
#include "masternode-sync.h"
-#include "masternodeman.h"
#include "netfulfilledman.h"
#include "netmessagemaker.h"
#include "ui_interface.h"
@@ -45,8 +44,6 @@ std::string CMasternodeSync::GetAssetName()
{
case(MASTERNODE_SYNC_INITIAL): return "MASTERNODE_SYNC_INITIAL";
case(MASTERNODE_SYNC_WAITING): return "MASTERNODE_SYNC_WAITING";
- case(MASTERNODE_SYNC_LIST): return "MASTERNODE_SYNC_LIST";
- case(MASTERNODE_SYNC_MNW): return "MASTERNODE_SYNC_MNW";
case(MASTERNODE_SYNC_GOVERNANCE): return "MASTERNODE_SYNC_GOVERNANCE";
case(MASTERNODE_SYNC_FAILED): return "MASTERNODE_SYNC_FAILED";
case MASTERNODE_SYNC_FINISHED: return "MASTERNODE_SYNC_FINISHED";
@@ -66,24 +63,6 @@ void CMasternodeSync::SwitchToNextAsset(CConnman& connman)
LogPrintf("CMasternodeSync::SwitchToNextAsset -- Starting %s\n", GetAssetName());
break;
case(MASTERNODE_SYNC_WAITING):
- LogPrintf("CMasternodeSync::SwitchToNextAsset -- Completed %s in %llds\n", GetAssetName(), GetTime() - nTimeAssetSyncStarted);
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
- nCurrentAsset = MASTERNODE_SYNC_GOVERNANCE;
- } else {
- nCurrentAsset = MASTERNODE_SYNC_LIST;
- }
- LogPrintf("CMasternodeSync::SwitchToNextAsset -- Starting %s\n", GetAssetName());
- break;
- case(MASTERNODE_SYNC_LIST):
- LogPrintf("CMasternodeSync::SwitchToNextAsset -- Completed %s in %llds\n", GetAssetName(), GetTime() - nTimeAssetSyncStarted);
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
- nCurrentAsset = MASTERNODE_SYNC_GOVERNANCE;
- } else {
- nCurrentAsset = MASTERNODE_SYNC_MNW;
- }
- LogPrintf("CMasternodeSync::SwitchToNextAsset -- Starting %s\n", GetAssetName());
- break;
- case(MASTERNODE_SYNC_MNW):
LogPrintf("CMasternodeSync::SwitchToNextAsset -- Completed %s in %llds\n", GetAssetName(), GetTime() - nTimeAssetSyncStarted);
nCurrentAsset = MASTERNODE_SYNC_GOVERNANCE;
LogPrintf("CMasternodeSync::SwitchToNextAsset -- Starting %s\n", GetAssetName());
@@ -92,8 +71,6 @@ void CMasternodeSync::SwitchToNextAsset(CConnman& connman)
LogPrintf("CMasternodeSync::SwitchToNextAsset -- Completed %s in %llds\n", GetAssetName(), GetTime() - nTimeAssetSyncStarted);
nCurrentAsset = MASTERNODE_SYNC_FINISHED;
uiInterface.NotifyAdditionalDataSyncProgressChanged(1);
- //try to activate our masternode if possible
- legacyActiveMasternodeManager.ManageState(connman);
connman.ForEachNode(CConnman::AllNodes, [](CNode* pnode) {
netfulfilledman.AddFulfilledRequest(pnode->addr, "full-sync");
@@ -112,8 +89,6 @@ std::string CMasternodeSync::GetSyncStatus()
switch (masternodeSync.nCurrentAsset) {
case MASTERNODE_SYNC_INITIAL: return _("Synchroning blockchain...");
case MASTERNODE_SYNC_WAITING: return _("Synchronization pending...");
- case MASTERNODE_SYNC_LIST: return _("Synchronizing masternodes...");
- case MASTERNODE_SYNC_MNW: return _("Synchronizing masternode payments...");
case MASTERNODE_SYNC_GOVERNANCE: return _("Synchronizing governance objects...");
case MASTERNODE_SYNC_FAILED: return _("Synchronization failed");
case MASTERNODE_SYNC_FINISHED: return _("Synchronization finished");
@@ -199,16 +174,6 @@ void CMasternodeSync::ProcessTick(CConnman& connman)
if (nCurrentAsset == MASTERNODE_SYNC_WAITING) {
connman.PushMessage(pnode, msgMaker.Make(NetMsgType::GETSPORKS)); //get current network sporks
SwitchToNextAsset(connman);
- } else if (nCurrentAsset == MASTERNODE_SYNC_LIST) {
- if (!deterministicMNManager->IsDeterministicMNsSporkActive()) {
- mnodeman.DsegUpdate(pnode, connman);
- }
- SwitchToNextAsset(connman);
- } else if (nCurrentAsset == MASTERNODE_SYNC_MNW) {
- if (!deterministicMNManager->IsDeterministicMNsSporkActive()) {
- connman.PushMessage(pnode, msgMaker.Make(NetMsgType::MASTERNODEPAYMENTSYNC)); //sync payment votes
- }
- SwitchToNextAsset(connman);
} else if (nCurrentAsset == MASTERNODE_SYNC_GOVERNANCE) {
SendGovernanceSyncRequest(pnode, connman);
SwitchToNextAsset(connman);
@@ -253,109 +218,6 @@ void CMasternodeSync::ProcessTick(CConnman& connman)
}
}
- // MNLIST : SYNC MASTERNODE LIST FROM OTHER CONNECTED CLIENTS
-
- if(nCurrentAsset == MASTERNODE_SYNC_LIST) {
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
- SwitchToNextAsset(connman);
- connman.ReleaseNodeVector(vNodesCopy);
- return;
- }
-
- LogPrint("masternode", "CMasternodeSync::ProcessTick -- nTick %d nCurrentAsset %d nTimeLastBumped %lld GetTime() %lld diff %lld\n", nTick, nCurrentAsset, nTimeLastBumped, GetTime(), GetTime() - nTimeLastBumped);
- // check for timeout first
- if(GetTime() - nTimeLastBumped > MASTERNODE_SYNC_TIMEOUT_SECONDS) {
- LogPrintf("CMasternodeSync::ProcessTick -- nTick %d nCurrentAsset %d -- timeout\n", nTick, nCurrentAsset);
- if (nTriedPeerCount == 0) {
- LogPrintf("CMasternodeSync::ProcessTick -- ERROR: failed to sync %s\n", GetAssetName());
- // there is no way we can continue without masternode list, fail here and try later
- Fail();
- connman.ReleaseNodeVector(vNodesCopy);
- return;
- }
- SwitchToNextAsset(connman);
- connman.ReleaseNodeVector(vNodesCopy);
- return;
- }
-
- // request from three peers max
- if (nTriedPeerCount > 2) {
- connman.ReleaseNodeVector(vNodesCopy);
- return;
- }
-
- // only request once from each peer
- if(netfulfilledman.HasFulfilledRequest(pnode->addr, "masternode-list-sync")) continue;
- netfulfilledman.AddFulfilledRequest(pnode->addr, "masternode-list-sync");
-
- if (pnode->nVersion < mnpayments.GetMinMasternodePaymentsProto()) continue;
- nTriedPeerCount++;
-
- mnodeman.DsegUpdate(pnode, connman);
-
- connman.ReleaseNodeVector(vNodesCopy);
- return; //this will cause each peer to get one request each six seconds for the various assets we need
- }
-
- // MNW : SYNC MASTERNODE PAYMENT VOTES FROM OTHER CONNECTED CLIENTS
-
- if(nCurrentAsset == MASTERNODE_SYNC_MNW) {
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
- SwitchToNextAsset(connman);
- connman.ReleaseNodeVector(vNodesCopy);
- return;
- }
-
- LogPrint("mnpayments", "CMasternodeSync::ProcessTick -- nTick %d nCurrentAsset %d nTimeLastBumped %lld GetTime() %lld diff %lld\n", nTick, nCurrentAsset, nTimeLastBumped, GetTime(), GetTime() - nTimeLastBumped);
- // check for timeout first
- // This might take a lot longer than MASTERNODE_SYNC_TIMEOUT_SECONDS due to new blocks,
- // but that should be OK and it should timeout eventually.
- if(GetTime() - nTimeLastBumped > MASTERNODE_SYNC_TIMEOUT_SECONDS) {
- LogPrintf("CMasternodeSync::ProcessTick -- nTick %d nCurrentAsset %d -- timeout\n", nTick, nCurrentAsset);
- if (nTriedPeerCount == 0) {
- LogPrintf("CMasternodeSync::ProcessTick -- ERROR: failed to sync %s\n", GetAssetName());
- // probably not a good idea to proceed without winner list
- Fail();
- connman.ReleaseNodeVector(vNodesCopy);
- return;
- }
- SwitchToNextAsset(connman);
- connman.ReleaseNodeVector(vNodesCopy);
- return;
- }
-
- // check for data
- // if mnpayments already has enough blocks and votes, switch to the next asset
- // try to fetch data from at least two peers though
- if(nTriedPeerCount > 1 && mnpayments.IsEnoughData()) {
- LogPrintf("CMasternodeSync::ProcessTick -- nTick %d nCurrentAsset %d -- found enough data\n", nTick, nCurrentAsset);
- SwitchToNextAsset(connman);
- connman.ReleaseNodeVector(vNodesCopy);
- return;
- }
-
- // request from three peers max
- if (nTriedPeerCount > 2) {
- connman.ReleaseNodeVector(vNodesCopy);
- return;
- }
-
- // only request once from each peer
- if(netfulfilledman.HasFulfilledRequest(pnode->addr, "masternode-payment-sync")) continue;
- netfulfilledman.AddFulfilledRequest(pnode->addr, "masternode-payment-sync");
-
- if(pnode->nVersion < mnpayments.GetMinMasternodePaymentsProto()) continue;
- nTriedPeerCount++;
-
- // ask node for all payment votes it has (new nodes will only return votes for future payments)
- connman.PushMessage(pnode, msgMaker.Make(NetMsgType::MASTERNODEPAYMENTSYNC));
- // ask node for missing pieces only (old nodes will not be asked)
- mnpayments.RequestLowDataPaymentBlocks(pnode, connman);
-
- connman.ReleaseNodeVector(vNodesCopy);
- return; //this will cause each peer to get one request each six seconds for the various assets we need
- }
-
// GOVOBJ : SYNC GOVERNANCE ITEMS FROM OUR PEERS
if(nCurrentAsset == MASTERNODE_SYNC_GOVERNANCE) {
diff --git a/src/masternode-sync.h b/src/masternode-sync.h
index 2d98c8a1cb10..13d2601c639a 100644
--- a/src/masternode-sync.h
+++ b/src/masternode-sync.h
@@ -12,8 +12,6 @@ class CMasternodeSync;
static const int MASTERNODE_SYNC_FAILED = -1;
static const int MASTERNODE_SYNC_INITIAL = 0; // sync just started, was reset recently or still in IDB
static const int MASTERNODE_SYNC_WAITING = 1; // waiting after initial to see if we can get more headers/blocks
-static const int MASTERNODE_SYNC_LIST = 2;
-static const int MASTERNODE_SYNC_MNW = 3;
static const int MASTERNODE_SYNC_GOVERNANCE = 4;
static const int MASTERNODE_SYNC_GOVOBJ = 10;
static const int MASTERNODE_SYNC_GOVOBJ_VOTE = 11;
@@ -53,8 +51,6 @@ class CMasternodeSync
bool IsFailed() { return nCurrentAsset == MASTERNODE_SYNC_FAILED; }
bool IsBlockchainSynced() { return nCurrentAsset > MASTERNODE_SYNC_WAITING; }
- bool IsMasternodeListSynced() { return nCurrentAsset > MASTERNODE_SYNC_LIST; }
- bool IsWinnersListSynced() { return nCurrentAsset > MASTERNODE_SYNC_MNW; }
bool IsSynced() { return nCurrentAsset == MASTERNODE_SYNC_FINISHED; }
int GetAssetID() { return nCurrentAsset; }
diff --git a/src/masternode-utils.cpp b/src/masternode-utils.cpp
new file mode 100644
index 000000000000..1e480491c551
--- /dev/null
+++ b/src/masternode-utils.cpp
@@ -0,0 +1,106 @@
+// Copyright (c) 2014-2018 The Dash Core developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "masternode-utils.h"
+
+#include "init.h"
+#include "masternode-sync.h"
+#include "privatesend-client.h"
+#include "validation.h"
+
+struct CompareScoreMN
+{
+ bool operator()(const std::pair& t1,
+ const std::pair& t2) const
+ {
+ return (t1.first != t2.first) ? (t1.first < t2.first) : (t1.second->collateralOutpoint < t2.second->collateralOutpoint);
+ }
+};
+
+bool CMasternodeUtils::GetMasternodeScores(const uint256& nBlockHash, score_pair_vec_t& vecMasternodeScoresRet)
+{
+ vecMasternodeScoresRet.clear();
+
+ auto mnList = deterministicMNManager->GetListAtChainTip();
+ auto scores = mnList.CalculateScores(nBlockHash);
+ for (const auto& p : scores) {
+ vecMasternodeScoresRet.emplace_back(p.first, p.second);
+ }
+
+ std::sort(vecMasternodeScoresRet.rbegin(), vecMasternodeScoresRet.rend(), CompareScoreMN());
+ return !vecMasternodeScoresRet.empty();
+}
+
+bool CMasternodeUtils::GetMasternodeRank(const COutPoint& outpoint, int& nRankRet, uint256& blockHashRet, int nBlockHeight)
+{
+ nRankRet = -1;
+
+ if (!masternodeSync.IsBlockchainSynced())
+ return false;
+
+ // make sure we know about this block
+ blockHashRet = uint256();
+ if (!GetBlockHash(blockHashRet, nBlockHeight)) {
+ LogPrintf("CMasternodeUtils::%s -- ERROR: GetBlockHash() failed at nBlockHeight %d\n", __func__, nBlockHeight);
+ return false;
+ }
+
+ score_pair_vec_t vecMasternodeScores;
+ if (!GetMasternodeScores(blockHashRet, vecMasternodeScores))
+ return false;
+
+ int nRank = 0;
+ for (const auto& scorePair : vecMasternodeScores) {
+ nRank++;
+ if(scorePair.second->collateralOutpoint == outpoint) {
+ nRankRet = nRank;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+void CMasternodeUtils::ProcessMasternodeConnections(CConnman& connman)
+{
+ std::vector vecDmns; // will be empty when no wallet
+#ifdef ENABLE_WALLET
+ privateSendClient.GetMixingMasternodesInfo(vecDmns);
+#endif // ENABLE_WALLET
+
+ connman.ForEachNode(CConnman::AllNodes, [&](CNode* pnode) {
+ if (pnode->fMasternode) {
+#ifdef ENABLE_WALLET
+ bool fFound = false;
+ for (const auto& dmn : vecDmns) {
+ if (pnode->addr == dmn->pdmnState->addr) {
+ fFound = true;
+ break;
+ }
+ }
+ if (fFound) return; // do NOT disconnect mixing masternodes
+#endif // ENABLE_WALLET
+ LogPrintf("Closing Masternode connection: peer=%d, addr=%s\n", pnode->id, pnode->addr.ToString());
+ pnode->fDisconnect = true;
+ }
+ });
+}
+
+void CMasternodeUtils::DoMaintenance(CConnman& connman)
+{
+ if(fLiteMode) return; // disable all Dash specific functionality
+
+ if(!masternodeSync.IsBlockchainSynced() || ShutdownRequested())
+ return;
+
+ static unsigned int nTick = 0;
+
+ nTick++;
+
+ if(nTick % 60 == 0) {
+ ProcessMasternodeConnections(connman);
+ }
+}
+
diff --git a/src/masternode-utils.h b/src/masternode-utils.h
new file mode 100644
index 000000000000..edabf5faa129
--- /dev/null
+++ b/src/masternode-utils.h
@@ -0,0 +1,28 @@
+// Copyright (c) 2014-2018 The Dash Core developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef MASTERNODE_UTILS_H
+#define MASTERNODE_UTILS_H
+
+#include "evo/deterministicmns.h"
+
+class CConnman;
+
+class CMasternodeUtils
+{
+public:
+ typedef std::pair score_pair_t;
+ typedef std::vector score_pair_vec_t;
+ typedef std::pair rank_pair_t;
+ typedef std::vector rank_pair_vec_t;
+
+public:
+ static bool GetMasternodeScores(const uint256& nBlockHash, score_pair_vec_t& vecMasternodeScoresRet);
+ static bool GetMasternodeRank(const COutPoint &outpoint, int& nRankRet, uint256& blockHashRet, int nBlockHeight = -1);
+
+ static void ProcessMasternodeConnections(CConnman& connman);
+ static void DoMaintenance(CConnman &connman);
+};
+
+#endif//MASTERNODE_UTILS_H
diff --git a/src/masternode.cpp b/src/masternode.cpp
deleted file mode 100644
index e89e49d6c8e2..000000000000
--- a/src/masternode.cpp
+++ /dev/null
@@ -1,992 +0,0 @@
-// Copyright (c) 2014-2017 The Dash Core developers
-// Distributed under the MIT/X11 software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#include "activemasternode.h"
-#include "base58.h"
-#include "clientversion.h"
-#include "init.h"
-#include "netbase.h"
-#include "masternode.h"
-#include "masternode-payments.h"
-#include "masternode-sync.h"
-#include "masternodeman.h"
-#include "messagesigner.h"
-#include "script/standard.h"
-#include "util.h"
-#ifdef ENABLE_WALLET
-#include "wallet/wallet.h"
-#endif // ENABLE_WALLET
-
-#include "evo/deterministicmns.h"
-
-#include
-
-
-CMasternode::CMasternode() :
- masternode_info_t{ MASTERNODE_ENABLED, PROTOCOL_VERSION, GetAdjustedTime()}
-{}
-
-CMasternode::CMasternode(CService addr, COutPoint outpoint, CPubKey pubKeyCollateralAddressNew, CPubKey pubKeyMasternodeNew, int nProtocolVersionIn) :
- masternode_info_t{ MASTERNODE_ENABLED, nProtocolVersionIn, GetAdjustedTime(),
- outpoint, addr, pubKeyCollateralAddressNew, pubKeyMasternodeNew}
-{}
-
-CMasternode::CMasternode(const CMasternode& other) :
- masternode_info_t{other},
- lastPing(other.lastPing),
- vchSig(other.vchSig),
- nCollateralMinConfBlockHash(other.nCollateralMinConfBlockHash),
- nBlockLastPaid(other.nBlockLastPaid),
- nPoSeBanScore(other.nPoSeBanScore),
- nPoSeBanHeight(other.nPoSeBanHeight),
- nMixingTxCount(other.nMixingTxCount),
- fUnitTest(other.fUnitTest)
-{}
-
-CMasternode::CMasternode(const CMasternodeBroadcast& mnb) :
- masternode_info_t{ mnb.nActiveState, mnb.nProtocolVersion, mnb.sigTime,
- mnb.outpoint, mnb.addr, mnb.pubKeyCollateralAddress, mnb.pubKeyMasternode},
- lastPing(mnb.lastPing),
- vchSig(mnb.vchSig)
-{}
-
-CMasternode::CMasternode(const uint256 &proTxHash, const CDeterministicMNCPtr& dmn) :
- masternode_info_t{ MASTERNODE_ENABLED, DMN_PROTO_VERSION, GetAdjustedTime(),
- dmn->collateralOutpoint, dmn->pdmnState->addr, CKeyID() /* not valid with DIP3 */, dmn->pdmnState->keyIDOwner, dmn->pdmnState->pubKeyOperator, dmn->pdmnState->keyIDVoting}
-{
-}
-
-//
-// When a new masternode broadcast is sent, update our information
-//
-bool CMasternode::UpdateFromNewBroadcast(CMasternodeBroadcast& mnb, CConnman& connman)
-{
- if(mnb.sigTime <= sigTime && !mnb.fRecovery) return false;
-
- pubKeyMasternode = mnb.pubKeyMasternode;
- keyIDOwner = mnb.pubKeyMasternode.GetID();
- legacyKeyIDOperator = mnb.pubKeyMasternode.GetID();
- keyIDVoting = mnb.pubKeyMasternode.GetID();
- sigTime = mnb.sigTime;
- vchSig = mnb.vchSig;
- nProtocolVersion = mnb.nProtocolVersion;
- addr = mnb.addr;
- nPoSeBanScore = 0;
- nPoSeBanHeight = 0;
- nTimeLastChecked = 0;
- int nDos = 0;
- if(!mnb.lastPing || (mnb.lastPing && mnb.lastPing.CheckAndUpdate(this, true, nDos, connman))) {
- lastPing = mnb.lastPing;
- mnodeman.mapSeenMasternodePing.insert(std::make_pair(lastPing.GetHash(), lastPing));
- }
- // if it matches our Masternode privkey...
- if(fMasternodeMode && legacyKeyIDOperator == activeMasternodeInfo.legacyKeyIDOperator) {
- nPoSeBanScore = -MASTERNODE_POSE_BAN_MAX_SCORE;
- if(nProtocolVersion == PROTOCOL_VERSION) {
- // ... and PROTOCOL_VERSION, then we've been remotely activated ...
- legacyActiveMasternodeManager.ManageState(connman);
- } else {
- // ... otherwise we need to reactivate our node, do not add it to the list and do not relay
- // but also do not ban the node we get this message from
- LogPrintf("CMasternode::UpdateFromNewBroadcast -- wrong PROTOCOL_VERSION, re-activate your MN: message nProtocolVersion=%d PROTOCOL_VERSION=%d\n", nProtocolVersion, PROTOCOL_VERSION);
- return false;
- }
- }
- return true;
-}
-
-//
-// Deterministically calculate a given "score" for a Masternode depending on how close it's hash is to
-// the proof of work for that block. The further away they are the better, the furthest will win the election
-// and get paid this block
-//
-arith_uint256 CMasternode::CalculateScore(const uint256& blockHash) const
-{
- // NOTE not called when deterministic masternodes (spork15) are activated
-
- // Deterministically calculate a "score" for a Masternode based on any given (block)hash
- CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
- ss << outpoint << nCollateralMinConfBlockHash << blockHash;
- return UintToArith256(ss.GetHash());
-}
-
-CMasternode::CollateralStatus CMasternode::CheckCollateral(const COutPoint& outpoint, const CKeyID& keyID)
-{
- int nHeight;
- return CheckCollateral(outpoint, keyID, nHeight);
-}
-
-CMasternode::CollateralStatus CMasternode::CheckCollateral(const COutPoint& outpoint, const CKeyID& keyID, int& nHeightRet)
-{
- AssertLockHeld(cs_main);
-
- Coin coin;
- if(!GetUTXOCoin(outpoint, coin)) {
- return COLLATERAL_UTXO_NOT_FOUND;
- }
-
- if(coin.out.nValue != 1000 * COIN) {
- return COLLATERAL_INVALID_AMOUNT;
- }
-
- if(keyID.IsNull() || coin.out.scriptPubKey != GetScriptForDestination(keyID)) {
- return COLLATERAL_INVALID_PUBKEY;
- }
-
- nHeightRet = coin.nHeight;
- return COLLATERAL_OK;
-}
-
-void CMasternode::Check(bool fForce)
-{
- AssertLockHeld(cs_main);
- LOCK(cs);
-
- if(ShutdownRequested()) return;
-
- if(!fForce && (GetTime() - nTimeLastChecked < MASTERNODE_CHECK_SECONDS)) return;
- nTimeLastChecked = GetTime();
-
- LogPrint("masternode", "CMasternode::Check -- Masternode %s is in %s state\n", outpoint.ToStringShort(), GetStateString());
-
- //once spent, stop doing the checks
- if(IsOutpointSpent()) return;
-
- int nHeight = 0;
- if(!fUnitTest) {
- Coin coin;
- if(!GetUTXOCoin(outpoint, coin)) {
- nActiveState = MASTERNODE_OUTPOINT_SPENT;
- LogPrint("masternode", "CMasternode::Check -- Failed to find Masternode UTXO, masternode=%s\n", outpoint.ToStringShort());
- return;
- }
-
- nHeight = chainActive.Height();
- }
-
- if(IsPoSeBanned()) {
- if(nHeight < nPoSeBanHeight) return; // too early?
- // Otherwise give it a chance to proceed further to do all the usual checks and to change its state.
- // Masternode still will be on the edge and can be banned back easily if it keeps ignoring mnverify
- // or connect attempts. Will require few mnverify messages to strengthen its position in mn list.
- LogPrintf("CMasternode::Check -- Masternode %s is unbanned and back in list now\n", outpoint.ToStringShort());
- DecreasePoSeBanScore();
- } else if(nPoSeBanScore >= MASTERNODE_POSE_BAN_MAX_SCORE) {
- nActiveState = MASTERNODE_POSE_BAN;
- // ban for the whole payment cycle
- nPoSeBanHeight = nHeight + mnodeman.size();
- LogPrintf("CMasternode::Check -- Masternode %s is banned till block %d now\n", outpoint.ToStringShort(), nPoSeBanHeight);
- return;
- }
-
- int nActiveStatePrev = nActiveState;
- bool fOurMasternode = fMasternodeMode && activeMasternodeInfo.legacyKeyIDOperator == legacyKeyIDOperator;
-
- // masternode doesn't meet payment protocol requirements ...
- bool fRequireUpdate = nProtocolVersion < mnpayments.GetMinMasternodePaymentsProto() ||
- // or it's our own node and we just updated it to the new protocol but we are still waiting for activation ...
- (fOurMasternode && nProtocolVersion < PROTOCOL_VERSION);
-
- if(fRequireUpdate) {
- nActiveState = MASTERNODE_UPDATE_REQUIRED;
- if(nActiveStatePrev != nActiveState) {
- LogPrint("masternode", "CMasternode::Check -- Masternode %s is in %s state now\n", outpoint.ToStringShort(), GetStateString());
- }
- return;
- }
-
- // keep old masternodes on start, give them a chance to receive updates...
- bool fWaitForPing = !masternodeSync.IsMasternodeListSynced() && !IsPingedWithin(MASTERNODE_MIN_MNP_SECONDS);
-
- if(fWaitForPing && !fOurMasternode) {
- // ...but if it was already expired before the initial check - return right away
- if(IsExpired() || IsSentinelPingExpired() || IsNewStartRequired()) {
- LogPrint("masternode", "CMasternode::Check -- Masternode %s is in %s state, waiting for ping\n", outpoint.ToStringShort(), GetStateString());
- return;
- }
- }
-
- // don't expire if we are still in "waiting for ping" mode unless it's our own masternode
- if(!fWaitForPing || fOurMasternode) {
-
- if(!IsPingedWithin(MASTERNODE_NEW_START_REQUIRED_SECONDS)) {
- nActiveState = MASTERNODE_NEW_START_REQUIRED;
- if(nActiveStatePrev != nActiveState) {
- LogPrint("masternode", "CMasternode::Check -- Masternode %s is in %s state now\n", outpoint.ToStringShort(), GetStateString());
- }
- return;
- }
-
- if(!IsPingedWithin(MASTERNODE_EXPIRATION_SECONDS)) {
- nActiveState = MASTERNODE_EXPIRED;
- if(nActiveStatePrev != nActiveState) {
- LogPrint("masternode", "CMasternode::Check -- Masternode %s is in %s state now\n", outpoint.ToStringShort(), GetStateString());
- }
- return;
- }
-
- // part 1: expire based on dashd ping
- bool fSentinelPingActive = masternodeSync.IsSynced() && mnodeman.IsSentinelPingActive();
- bool fSentinelPingExpired = fSentinelPingActive && !IsPingedWithin(MASTERNODE_SENTINEL_PING_MAX_SECONDS);
- LogPrint("masternode", "CMasternode::Check -- outpoint=%s, GetAdjustedTime()=%d, fSentinelPingExpired=%d\n",
- outpoint.ToStringShort(), GetAdjustedTime(), fSentinelPingExpired);
-
- if(fSentinelPingExpired) {
- nActiveState = MASTERNODE_SENTINEL_PING_EXPIRED;
- if(nActiveStatePrev != nActiveState) {
- LogPrint("masternode", "CMasternode::Check -- Masternode %s is in %s state now\n", outpoint.ToStringShort(), GetStateString());
- }
- return;
- }
- }
-
- // We require MNs to be in PRE_ENABLED until they either start to expire or receive a ping and go into ENABLED state
- // Works on mainnet/testnet only and not the case on regtest/devnet.
- if (Params().NetworkIDString() != CBaseChainParams::REGTEST && Params().NetworkIDString() != CBaseChainParams::DEVNET) {
- if (lastPing.sigTime - sigTime < MASTERNODE_MIN_MNP_SECONDS) {
- nActiveState = MASTERNODE_PRE_ENABLED;
- if (nActiveStatePrev != nActiveState) {
- LogPrint("masternode", "CMasternode::Check -- Masternode %s is in %s state now\n", outpoint.ToStringShort(), GetStateString());
- }
- return;
- }
- }
-
- if(!fWaitForPing || fOurMasternode) {
- // part 2: expire based on sentinel info
- bool fSentinelPingActive = masternodeSync.IsSynced() && mnodeman.IsSentinelPingActive();
- bool fSentinelPingExpired = fSentinelPingActive && !lastPing.fSentinelIsCurrent;
-
- LogPrint("masternode", "CMasternode::Check -- outpoint=%s, GetAdjustedTime()=%d, fSentinelPingExpired=%d\n",
- outpoint.ToStringShort(), GetAdjustedTime(), fSentinelPingExpired);
-
- if(fSentinelPingExpired) {
- nActiveState = MASTERNODE_SENTINEL_PING_EXPIRED;
- if(nActiveStatePrev != nActiveState) {
- LogPrint("masternode", "CMasternode::Check -- Masternode %s is in %s state now\n", outpoint.ToStringShort(), GetStateString());
- }
- return;
- }
- }
-
- nActiveState = MASTERNODE_ENABLED; // OK
- if(nActiveStatePrev != nActiveState) {
- LogPrint("masternode", "CMasternode::Check -- Masternode %s is in %s state now\n", outpoint.ToStringShort(), GetStateString());
- }
-}
-
-bool CMasternode::IsValidNetAddr()
-{
- return IsValidNetAddr(addr);
-}
-
-bool CMasternode::IsValidNetAddr(CService addrIn)
-{
- // TODO: regtest is fine with any addresses for now,
- // should probably be a bit smarter if one day we start to implement tests for this
- return Params().NetworkIDString() == CBaseChainParams::REGTEST ||
- (addrIn.IsIPv4() && IsReachable(addrIn) && addrIn.IsRoutable());
-}
-
-masternode_info_t CMasternode::GetInfo() const
-{
- masternode_info_t info{*this};
- info.nTimeLastPing = lastPing.sigTime;
- info.fInfoValid = true;
- return info;
-}
-
-std::string CMasternode::StateToString(int nStateIn)
-{
- switch(nStateIn) {
- case MASTERNODE_PRE_ENABLED: return "PRE_ENABLED";
- case MASTERNODE_ENABLED: return "ENABLED";
- case MASTERNODE_EXPIRED: return "EXPIRED";
- case MASTERNODE_OUTPOINT_SPENT: return "OUTPOINT_SPENT";
- case MASTERNODE_UPDATE_REQUIRED: return "UPDATE_REQUIRED";
- case MASTERNODE_SENTINEL_PING_EXPIRED: return "SENTINEL_PING_EXPIRED";
- case MASTERNODE_NEW_START_REQUIRED: return "NEW_START_REQUIRED";
- case MASTERNODE_POSE_BAN: return "POSE_BAN";
- default: return "UNKNOWN";
- }
-}
-
-std::string CMasternode::GetStateString() const
-{
- return StateToString(nActiveState);
-}
-
-std::string CMasternode::GetStatus() const
-{
- // TODO: return smth a bit more human readable here
- return GetStateString();
-}
-
-void CMasternode::UpdateLastPaid(const CBlockIndex *pindex, int nMaxBlocksToScanBack)
-{
- AssertLockHeld(cs_main);
-
- if(!pindex) return;
-
- if (deterministicMNManager->IsDeterministicMNsSporkActive(pindex->nHeight)) {
- auto dmn = deterministicMNManager->GetListForBlock(pindex->GetBlockHash()).GetMNByCollateral(outpoint);
- if (!dmn || dmn->pdmnState->nLastPaidHeight == -1) {
- LogPrint("masternode", "CMasternode::UpdateLastPaidBlock -- searching for block with payment to %s -- not found\n", outpoint.ToStringShort());
- } else {
- nBlockLastPaid = (int)dmn->pdmnState->nLastPaidHeight;
- nTimeLastPaid = chainActive[nBlockLastPaid]->nTime;
- LogPrint("masternode", "CMasternode::UpdateLastPaidBlock -- searching for block with payment to %s -- found new %d\n", outpoint.ToStringShort(), nBlockLastPaid);
- }
- return;
- }
-
- const CBlockIndex *BlockReading = pindex;
-
- CScript mnpayee = GetScriptForDestination(keyIDCollateralAddress);
- // LogPrint("mnpayments", "CMasternode::UpdateLastPaidBlock -- searching for block with payment to %s\n", outpoint.ToStringShort());
-
- LOCK(cs_mapMasternodeBlocks);
-
- for (int i = 0; BlockReading && BlockReading->nHeight > nBlockLastPaid && i < nMaxBlocksToScanBack; i++) {
- if(mnpayments.mapMasternodeBlocks.count(BlockReading->nHeight) &&
- mnpayments.mapMasternodeBlocks[BlockReading->nHeight].HasPayeeWithVotes(mnpayee, 2))
- {
- CBlock block;
- if(!ReadBlockFromDisk(block, BlockReading, Params().GetConsensus()))
- continue; // shouldn't really happen
-
- CAmount nMasternodePayment = GetMasternodePayment(BlockReading->nHeight, block.vtx[0]->GetValueOut());
-
- for (const auto& txout : block.vtx[0]->vout)
- if(mnpayee == txout.scriptPubKey && nMasternodePayment == txout.nValue) {
- nBlockLastPaid = BlockReading->nHeight;
- nTimeLastPaid = BlockReading->nTime;
- LogPrint("mnpayments", "CMasternode::UpdateLastPaidBlock -- searching for block with payment to %s -- found new %d\n", outpoint.ToStringShort(), nBlockLastPaid);
- return;
- }
- }
-
- if (BlockReading->pprev == nullptr) { assert(BlockReading); break; }
- BlockReading = BlockReading->pprev;
- }
-
- // Last payment for this masternode wasn't found in latest mnpayments blocks
- // or it was found in mnpayments blocks but wasn't found in the blockchain.
- // LogPrint("mnpayments", "CMasternode::UpdateLastPaidBlock -- searching for block with payment to %s -- keeping old %d\n", outpoint.ToStringShort(), nBlockLastPaid);
-}
-
-#ifdef ENABLE_WALLET
-bool CMasternodeBroadcast::Create(const std::string& strService, const std::string& strKeyMasternode, const std::string& strTxHash, const std::string& strOutputIndex, std::string& strErrorRet, CMasternodeBroadcast &mnbRet, bool fOffline)
-{
- COutPoint outpoint;
- CPubKey pubKeyCollateralAddressNew;
- CKey keyCollateralAddressNew;
- CPubKey pubKeyMasternodeNew;
- CKey keyMasternodeNew;
-
- auto Log = [&strErrorRet](std::string sErr)->bool
- {
- strErrorRet = sErr;
- LogPrintf("CMasternodeBroadcast::Create -- %s\n", strErrorRet);
- return false;
- };
-
- // Wait for sync to finish because mnb simply won't be relayed otherwise
- if (!fOffline && !masternodeSync.IsSynced())
- return Log("Sync in progress. Must wait until sync is complete to start Masternode");
-
- if (!CMessageSigner::GetKeysFromSecret(strKeyMasternode, keyMasternodeNew, pubKeyMasternodeNew))
- return Log(strprintf("Invalid masternode key %s", strKeyMasternode));
-
- if (!pwalletMain->GetMasternodeOutpointAndKeys(outpoint, pubKeyCollateralAddressNew, keyCollateralAddressNew, strTxHash, strOutputIndex))
- return Log(strprintf("Could not allocate outpoint %s:%s for masternode %s", strTxHash, strOutputIndex, strService));
-
- CService service;
- if (!Lookup(strService.c_str(), service, 0, false))
- return Log(strprintf("Invalid address %s for masternode.", strService));
- int mainnetDefaultPort = Params(CBaseChainParams::MAIN).GetDefaultPort();
- if (Params().NetworkIDString() == CBaseChainParams::MAIN) {
- if (service.GetPort() != mainnetDefaultPort)
- return Log(strprintf("Invalid port %u for masternode %s, only %d is supported on mainnet.", service.GetPort(), strService, mainnetDefaultPort));
- } else if (service.GetPort() == mainnetDefaultPort)
- return Log(strprintf("Invalid port %u for masternode %s, %d is the only supported on mainnet.", service.GetPort(), strService, mainnetDefaultPort));
-
- return Create(outpoint, service, keyCollateralAddressNew, pubKeyCollateralAddressNew, keyMasternodeNew, pubKeyMasternodeNew, strErrorRet, mnbRet);
-}
-
-bool CMasternodeBroadcast::Create(const COutPoint& outpoint, const CService& service, const CKey& keyCollateralAddressNew, const CPubKey& pubKeyCollateralAddressNew, const CKey& keyMasternodeNew, const CPubKey& pubKeyMasternodeNew, std::string &strErrorRet, CMasternodeBroadcast &mnbRet)
-{
- // wait for reindex and/or import to finish
- if (fImporting || fReindex) return false;
-
- LogPrint("masternode", "CMasternodeBroadcast::Create -- pubKeyCollateralAddressNew = %s, keyIDOperator = %s\n",
- CBitcoinAddress(pubKeyCollateralAddressNew.GetID()).ToString(),
- pubKeyMasternodeNew.GetID().ToString());
-
- auto Log = [&strErrorRet,&mnbRet](std::string sErr)->bool
- {
- strErrorRet = sErr;
- LogPrintf("CMasternodeBroadcast::Create -- %s\n", strErrorRet);
- mnbRet = CMasternodeBroadcast();
- return false;
- };
-
- CMasternodePing mnp(outpoint);
- if (!mnp.Sign(keyMasternodeNew, pubKeyMasternodeNew.GetID()))
- return Log(strprintf("Failed to sign ping, masternode=%s", outpoint.ToStringShort()));
-
- mnbRet = CMasternodeBroadcast(service, outpoint, pubKeyCollateralAddressNew, pubKeyMasternodeNew, PROTOCOL_VERSION);
-
- if (!mnbRet.IsValidNetAddr())
- return Log(strprintf("Invalid IP address, masternode=%s", outpoint.ToStringShort()));
-
- mnbRet.lastPing = mnp;
- if (!mnbRet.Sign(keyCollateralAddressNew))
- return Log(strprintf("Failed to sign broadcast, masternode=%s", outpoint.ToStringShort()));
-
- return true;
-}
-#endif // ENABLE_WALLET
-
-bool CMasternodeBroadcast::SimpleCheck(int& nDos)
-{
- nDos = 0;
-
- AssertLockHeld(cs_main);
-
- // make sure addr is valid
- if(!IsValidNetAddr()) {
- LogPrintf("CMasternodeBroadcast::SimpleCheck -- Invalid addr, rejected: masternode=%s addr=%s\n",
- outpoint.ToStringShort(), addr.ToString());
- return false;
- }
-
- // make sure signature isn't in the future (past is OK)
- if (sigTime > GetAdjustedTime() + 60 * 60) {
- LogPrintf("CMasternodeBroadcast::SimpleCheck -- Signature rejected, too far into the future: masternode=%s\n", outpoint.ToStringShort());
- nDos = 1;
- return false;
- }
-
- // empty ping or incorrect sigTime/unknown blockhash
- if(!lastPing || !lastPing.SimpleCheck(nDos)) {
- // one of us is probably forked or smth, just mark it as expired and check the rest of the rules
- nActiveState = MASTERNODE_EXPIRED;
- }
-
- if(nProtocolVersion < mnpayments.GetMinMasternodePaymentsProto()) {
- LogPrintf("CMasternodeBroadcast::SimpleCheck -- outdated Masternode: masternode=%s nProtocolVersion=%d\n", outpoint.ToStringShort(), nProtocolVersion);
- nActiveState = MASTERNODE_UPDATE_REQUIRED;
- }
-
- CScript pubkeyScript;
- pubkeyScript = GetScriptForDestination(keyIDCollateralAddress);
-
- if(pubkeyScript.size() != 25) {
- LogPrintf("CMasternodeBroadcast::SimpleCheck -- keyIDCollateralAddress has the wrong size\n");
- nDos = 100;
- return false;
- }
-
- CScript pubkeyScript2;
- pubkeyScript2 = GetScriptForDestination(legacyKeyIDOperator);
-
- if(pubkeyScript2.size() != 25) {
- LogPrintf("CMasternodeBroadcast::SimpleCheck -- keyIDOperator has the wrong size\n");
- nDos = 100;
- return false;
- }
-
- int mainnetDefaultPort = Params(CBaseChainParams::MAIN).GetDefaultPort();
- if(Params().NetworkIDString() == CBaseChainParams::MAIN) {
- if(addr.GetPort() != mainnetDefaultPort) return false;
- } else if(addr.GetPort() == mainnetDefaultPort) return false;
-
- return true;
-}
-
-bool CMasternodeBroadcast::Update(CMasternode* pmn, int& nDos, CConnman& connman)
-{
- nDos = 0;
-
- AssertLockHeld(cs_main);
-
- if(pmn->sigTime == sigTime && !fRecovery) {
- // mapSeenMasternodeBroadcast in CMasternodeMan::CheckMnbAndUpdateMasternodeList should filter legit duplicates
- // but this still can happen if we just started, which is ok, just do nothing here.
- return false;
- }
-
- // this broadcast is older than the one that we already have - it's bad and should never happen
- // unless someone is doing something fishy
- if(pmn->sigTime > sigTime) {
- LogPrintf("CMasternodeBroadcast::Update -- Bad sigTime %d (existing broadcast is at %d) for Masternode %s %s\n",
- sigTime, pmn->sigTime, outpoint.ToStringShort(), addr.ToString());
- return false;
- }
-
- pmn->Check();
-
- // masternode is banned by PoSe
- if(pmn->IsPoSeBanned()) {
- LogPrintf("CMasternodeBroadcast::Update -- Banned by PoSe, masternode=%s\n", outpoint.ToStringShort());
- return false;
- }
-
- // IsVnAssociatedWithPubkey is validated once in CheckOutpoint, after that they just need to match
- if(pmn->keyIDCollateralAddress != keyIDCollateralAddress) {
- LogPrintf("CMasternodeBroadcast::Update -- Got mismatched keyIDCollateralAddress and outpoint\n");
- nDos = 33;
- return false;
- }
-
- if (!CheckSignature(nDos)) {
- LogPrintf("CMasternodeBroadcast::Update -- CheckSignature() failed, masternode=%s\n", outpoint.ToStringShort());
- return false;
- }
-
- // if ther was no masternode broadcast recently or if it matches our Masternode privkey...
- if(!pmn->IsBroadcastedWithin(MASTERNODE_MIN_MNB_SECONDS) || (fMasternodeMode && legacyKeyIDOperator == activeMasternodeInfo.legacyKeyIDOperator)) {
- // take the newest entry
- LogPrintf("CMasternodeBroadcast::Update -- Got UPDATED Masternode entry: addr=%s\n", addr.ToString());
- if(pmn->UpdateFromNewBroadcast(*this, connman)) {
- pmn->Check();
- Relay(connman);
- }
- masternodeSync.BumpAssetLastTime("CMasternodeBroadcast::Update");
- }
-
- return true;
-}
-
-bool CMasternodeBroadcast::CheckOutpoint(int& nDos)
-{
- // we are a masternode with the same outpoint (i.e. already activated) and this mnb is ours (matches our Masternode privkey)
- // so nothing to do here for us
- if(fMasternodeMode && outpoint == activeMasternodeInfo.outpoint && legacyKeyIDOperator == activeMasternodeInfo.legacyKeyIDOperator) {
- return false;
- }
-
- AssertLockHeld(cs_main);
-
- int nHeight;
- CollateralStatus err = CheckCollateral(outpoint, keyIDCollateralAddress, nHeight);
- if (err == COLLATERAL_UTXO_NOT_FOUND) {
- LogPrint("masternode", "CMasternodeBroadcast::CheckOutpoint -- Failed to find Masternode UTXO, masternode=%s\n", outpoint.ToStringShort());
- return false;
- }
-
- if (err == COLLATERAL_INVALID_AMOUNT) {
- LogPrint("masternode", "CMasternodeBroadcast::CheckOutpoint -- Masternode UTXO should have 1000 DASH, masternode=%s\n", outpoint.ToStringShort());
- nDos = 33;
- return false;
- }
-
- if(err == COLLATERAL_INVALID_PUBKEY) {
- LogPrint("masternode", "CMasternodeBroadcast::CheckOutpoint -- Masternode UTXO should match keyIDCollateralAddress, masternode=%s\n", outpoint.ToStringShort());
- nDos = 33;
- return false;
- }
-
- if(chainActive.Height() - nHeight + 1 < Params().GetConsensus().nMasternodeMinimumConfirmations) {
- LogPrintf("CMasternodeBroadcast::CheckOutpoint -- Masternode UTXO must have at least %d confirmations, masternode=%s\n",
- Params().GetConsensus().nMasternodeMinimumConfirmations, outpoint.ToStringShort());
- // UTXO is legit but has not enough confirmations.
- // Maybe we miss few blocks, let this mnb be checked again later.
- mnodeman.mapSeenMasternodeBroadcast.erase(GetHash());
- return false;
- }
-
- LogPrint("masternode", "CMasternodeBroadcast::CheckOutpoint -- Masternode UTXO verified\n");
-
- // Verify that sig time is legit, should be at least not earlier than the timestamp of the block
- // at which collateral became nMasternodeMinimumConfirmations blocks deep.
- // NOTE: this is not accurate because block timestamp is NOT guaranteed to be 100% correct one.
- CBlockIndex* pRequiredConfIndex = chainActive[nHeight + Params().GetConsensus().nMasternodeMinimumConfirmations - 1]; // block where tx got nMasternodeMinimumConfirmations
- if(pRequiredConfIndex->GetBlockTime() > sigTime) {
- LogPrintf("CMasternodeBroadcast::CheckOutpoint -- Bad sigTime %d (%d conf block is at %d) for Masternode %s %s\n",
- sigTime, Params().GetConsensus().nMasternodeMinimumConfirmations, pRequiredConfIndex->GetBlockTime(), outpoint.ToStringShort(), addr.ToString());
- return false;
- }
-
- if (!CheckSignature(nDos)) {
- LogPrintf("CMasternodeBroadcast::CheckOutpoint -- CheckSignature() failed, masternode=%s\n", outpoint.ToStringShort());
- return false;
- }
-
- // remember the block hash when collateral for this masternode had minimum required confirmations
- nCollateralMinConfBlockHash = pRequiredConfIndex->GetBlockHash();
-
- return true;
-}
-
-uint256 CMasternodeBroadcast::GetHash() const
-{
- // Note: doesn't match serialization
-
- CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
- ss << outpoint << uint8_t{} << 0xffffffff; // adding dummy values here to match old hashing format
- ss << pubKeyCollateralAddress;
- ss << sigTime;
- return ss.GetHash();
-}
-
-uint256 CMasternodeBroadcast::GetSignatureHash() const
-{
- // TODO: replace with "return SerializeHash(*this);" after migration to 70209
- CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
- ss << outpoint;
- ss << addr;
- ss << pubKeyCollateralAddress;
- ss << pubKeyMasternode;
- ss << sigTime;
- ss << nProtocolVersion;
- return ss.GetHash();
-}
-
-bool CMasternodeBroadcast::Sign(const CKey& keyCollateralAddress)
-{
- std::string strError;
-
- sigTime = GetAdjustedTime();
-
- if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
- uint256 hash = GetSignatureHash();
-
- if (!CHashSigner::SignHash(hash, keyCollateralAddress, vchSig)) {
- LogPrintf("CMasternodeBroadcast::Sign -- SignHash() failed\n");
- return false;
- }
-
- if (!CHashSigner::VerifyHash(hash, keyIDCollateralAddress, vchSig, strError)) {
- LogPrintf("CMasternodeBroadcast::Sign -- VerifyMessage() failed, error: %s\n", strError);
- return false;
- }
- } else {
- std::string strMessage = addr.ToString(false) + std::to_string(sigTime) +
- keyIDCollateralAddress.ToString() + legacyKeyIDOperator.ToString() +
- std::to_string(nProtocolVersion);
-
- if (!CMessageSigner::SignMessage(strMessage, vchSig, keyCollateralAddress)) {
- LogPrintf("CMasternodeBroadcast::Sign -- SignMessage() failed\n");
- return false;
- }
-
- if(!CMessageSigner::VerifyMessage(keyIDCollateralAddress, vchSig, strMessage, strError)) {
- LogPrintf("CMasternodeBroadcast::Sign -- VerifyMessage() failed, error: %s\n", strError);
- return false;
- }
- }
-
- return true;
-}
-
-bool CMasternodeBroadcast::CheckSignature(int& nDos) const
-{
- std::string strError = "";
- nDos = 0;
-
- if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
- uint256 hash = GetSignatureHash();
-
- if (!CHashSigner::VerifyHash(hash, keyIDCollateralAddress, vchSig, strError)) {
- // maybe it's in old format
- std::string strMessage = addr.ToString(false) + std::to_string(sigTime) +
- keyIDCollateralAddress.ToString() + legacyKeyIDOperator.ToString() +
- std::to_string(nProtocolVersion);
-
- if (!CMessageSigner::VerifyMessage(keyIDCollateralAddress, vchSig, strMessage, strError)){
- // nope, not in old format either
- LogPrintf("CMasternodeBroadcast::CheckSignature -- Got bad Masternode announce signature, error: %s\n", strError);
- nDos = 100;
- return false;
- }
- }
- } else {
- std::string strMessage = addr.ToString(false) + std::to_string(sigTime) +
- keyIDCollateralAddress.ToString() + legacyKeyIDOperator.ToString() +
- std::to_string(nProtocolVersion);
-
- if(!CMessageSigner::VerifyMessage(keyIDCollateralAddress, vchSig, strMessage, strError)){
- LogPrintf("CMasternodeBroadcast::CheckSignature -- Got bad Masternode announce signature, error: %s\n", strError);
- nDos = 100;
- return false;
- }
- }
-
- return true;
-}
-
-void CMasternodeBroadcast::Relay(CConnman& connman) const
-{
- // Do not relay until fully synced
- if(!masternodeSync.IsSynced()) {
- LogPrint("masternode", "CMasternodeBroadcast::Relay -- won't relay until fully synced\n");
- return;
- }
-
- CInv inv(MSG_MASTERNODE_ANNOUNCE, GetHash());
- connman.RelayInv(inv);
-}
-
-uint256 CMasternodePing::GetHash() const
-{
- CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
- if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
- // TODO: replace with "return SerializeHash(*this);" after migration to 70209
- ss << masternodeOutpoint;
- ss << blockHash;
- ss << sigTime;
- ss << fSentinelIsCurrent;
- ss << nSentinelVersion;
- ss << nDaemonVersion;
- } else {
- // Note: doesn't match serialization
-
- ss << masternodeOutpoint << uint8_t{} << 0xffffffff; // adding dummy values here to match old hashing format
- ss << sigTime;
- }
- return ss.GetHash();
-}
-
-uint256 CMasternodePing::GetSignatureHash() const
-{
- return GetHash();
-}
-
-CMasternodePing::CMasternodePing(const COutPoint& outpoint)
-{
- LOCK(cs_main);
- if (!chainActive.Tip() || chainActive.Height() < 12) return;
-
- masternodeOutpoint = outpoint;
- blockHash = chainActive[chainActive.Height() - 12]->GetBlockHash();
- sigTime = GetAdjustedTime();
- nDaemonVersion = CLIENT_VERSION;
-}
-
-bool CMasternodePing::Sign(const CKey& keyMasternode, const CKeyID& keyIDOperator)
-{
- std::string strError;
-
- sigTime = GetAdjustedTime();
-
- if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
- uint256 hash = GetSignatureHash();
-
- if (!CHashSigner::SignHash(hash, keyMasternode, vchSig)) {
- LogPrintf("CMasternodePing::Sign -- SignHash() failed\n");
- return false;
- }
-
- if (!CHashSigner::VerifyHash(hash, keyIDOperator, vchSig, strError)) {
- LogPrintf("CMasternodePing::Sign -- VerifyHash() failed, error: %s\n", strError);
- return false;
- }
- } else {
- std::string strMessage = CTxIn(masternodeOutpoint).ToString() + blockHash.ToString() +
- std::to_string(sigTime);
-
- if (!CMessageSigner::SignMessage(strMessage, vchSig, keyMasternode)) {
- LogPrintf("CMasternodePing::Sign -- SignMessage() failed\n");
- return false;
- }
-
- if(!CMessageSigner::VerifyMessage(keyIDOperator, vchSig, strMessage, strError)) {
- LogPrintf("CMasternodePing::Sign -- VerifyMessage() failed, error: %s\n", strError);
- return false;
- }
- }
-
- return true;
-}
-
-bool CMasternodePing::CheckSignature(CKeyID& keyIDOperator, int &nDos) const
-{
- std::string strError = "";
- nDos = 0;
-
- if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
- uint256 hash = GetSignatureHash();
-
- if (!CHashSigner::VerifyHash(hash, keyIDOperator, vchSig, strError)) {
- std::string strMessage = CTxIn(masternodeOutpoint).ToString() + blockHash.ToString() +
- std::to_string(sigTime);
-
- if(!CMessageSigner::VerifyMessage(keyIDOperator, vchSig, strMessage, strError)) {
- LogPrintf("CMasternodePing::CheckSignature -- Got bad Masternode ping signature, masternode=%s, error: %s\n", masternodeOutpoint.ToStringShort(), strError);
- nDos = 33;
- return false;
- }
- }
- } else {
- std::string strMessage = CTxIn(masternodeOutpoint).ToString() + blockHash.ToString() +
- std::to_string(sigTime);
-
- if (!CMessageSigner::VerifyMessage(keyIDOperator, vchSig, strMessage, strError)) {
- LogPrintf("CMasternodePing::CheckSignature -- Got bad Masternode ping signature, masternode=%s, error: %s\n", masternodeOutpoint.ToStringShort(), strError);
- nDos = 33;
- return false;
- }
- }
-
- return true;
-}
-
-bool CMasternodePing::SimpleCheck(int& nDos)
-{
- // don't ban by default
- nDos = 0;
-
- if (sigTime > GetAdjustedTime() + 60 * 60) {
- LogPrintf("CMasternodePing::SimpleCheck -- Signature rejected, too far into the future, masternode=%s\n", masternodeOutpoint.ToStringShort());
- nDos = 1;
- return false;
- }
-
- {
- AssertLockHeld(cs_main);
- BlockMap::iterator mi = mapBlockIndex.find(blockHash);
- if (mi == mapBlockIndex.end()) {
- LogPrint("masternode", "CMasternodePing::SimpleCheck -- Masternode ping is invalid, unknown block hash: masternode=%s blockHash=%s\n", masternodeOutpoint.ToStringShort(), blockHash.ToString());
- // maybe we stuck or forked so we shouldn't ban this node, just fail to accept this ping
- // TODO: or should we also request this block?
- return false;
- }
- }
-
- LogPrint("masternode", "CMasternodePing::SimpleCheck -- Masternode ping verified: masternode=%s blockHash=%s sigTime=%d\n", masternodeOutpoint.ToStringShort(), blockHash.ToString(), sigTime);
- return true;
-}
-
-bool CMasternodePing::CheckAndUpdate(CMasternode* pmn, bool fFromNewBroadcast, int& nDos, CConnman& connman)
-{
- AssertLockHeld(cs_main);
-
- // don't ban by default
- nDos = 0;
-
- if (!SimpleCheck(nDos)) {
- return false;
- }
-
- if (pmn == nullptr) {
- LogPrint("masternode", "CMasternodePing::CheckAndUpdate -- Couldn't find Masternode entry, masternode=%s\n", masternodeOutpoint.ToStringShort());
- return false;
- }
-
- if(!fFromNewBroadcast) {
- if (pmn->IsUpdateRequired()) {
- LogPrint("masternode", "CMasternodePing::CheckAndUpdate -- masternode protocol is outdated, masternode=%s\n", masternodeOutpoint.ToStringShort());
- return false;
- }
-
- if (pmn->IsNewStartRequired()) {
- LogPrint("masternode", "CMasternodePing::CheckAndUpdate -- masternode is completely expired, new start is required, masternode=%s\n", masternodeOutpoint.ToStringShort());
- return false;
- }
- }
-
- {
- BlockMap::iterator mi = mapBlockIndex.find(blockHash);
- if ((*mi).second && (*mi).second->nHeight < chainActive.Height() - 24) {
- LogPrintf("CMasternodePing::CheckAndUpdate -- Masternode ping is invalid, block hash is too old: masternode=%s blockHash=%s\n", masternodeOutpoint.ToStringShort(), blockHash.ToString());
- // nDos = 1;
- return false;
- }
- }
-
- LogPrint("masternode", "CMasternodePing::CheckAndUpdate -- New ping: masternode=%s blockHash=%s sigTime=%d\n", masternodeOutpoint.ToStringShort(), blockHash.ToString(), sigTime);
-
- // LogPrintf("mnping - Found corresponding mn for outpoint: %s\n", masternodeOutpoint.ToStringShort());
- // update only if there is no known ping for this masternode or
- // last ping was more then MASTERNODE_MIN_MNP_SECONDS-60 ago comparing to this one
- if (pmn->IsPingedWithin(MASTERNODE_MIN_MNP_SECONDS - 60, sigTime)) {
- LogPrint("masternode", "CMasternodePing::CheckAndUpdate -- Masternode ping arrived too early, masternode=%s\n", masternodeOutpoint.ToStringShort());
- //nDos = 1; //disable, this is happening frequently and causing banned peers
- return false;
- }
-
- if (!CheckSignature(pmn->legacyKeyIDOperator, nDos)) return false;
-
- // so, ping seems to be ok
-
- // if we are still syncing and there was no known ping for this mn for quite a while
- // (NOTE: assuming that MASTERNODE_EXPIRATION_SECONDS/2 should be enough to finish mn list sync)
- if(!masternodeSync.IsMasternodeListSynced() && !pmn->IsPingedWithin(MASTERNODE_EXPIRATION_SECONDS/2)) {
- // let's bump sync timeout
- LogPrint("masternode", "CMasternodePing::CheckAndUpdate -- bumping sync timeout, masternode=%s\n", masternodeOutpoint.ToStringShort());
- masternodeSync.BumpAssetLastTime("CMasternodePing::CheckAndUpdate");
- }
-
- // let's store this ping as the last one
- LogPrint("masternode", "CMasternodePing::CheckAndUpdate -- Masternode ping accepted, masternode=%s\n", masternodeOutpoint.ToStringShort());
- pmn->lastPing = *this;
-
- // and update mnodeman.mapSeenMasternodeBroadcast.lastPing which is probably outdated
- CMasternodeBroadcast mnb(*pmn);
- uint256 hash = mnb.GetHash();
- if (mnodeman.mapSeenMasternodeBroadcast.count(hash)) {
- mnodeman.mapSeenMasternodeBroadcast[hash].second.lastPing = *this;
- }
-
- // force update, ignoring cache
- pmn->Check(true);
- // relay ping for nodes in ENABLED/EXPIRED/SENTINEL_PING_EXPIRED state only, skip everyone else
- if (!pmn->IsEnabled() && !pmn->IsExpired() && !pmn->IsSentinelPingExpired()) return false;
-
- LogPrint("masternode", "CMasternodePing::CheckAndUpdate -- Masternode ping acceepted and relayed, masternode=%s\n", masternodeOutpoint.ToStringShort());
- Relay(connman);
-
- return true;
-}
-
-void CMasternodePing::Relay(CConnman& connman)
-{
- // Do not relay until fully synced
- if(!masternodeSync.IsSynced()) {
- LogPrint("masternode", "CMasternodePing::Relay -- won't relay until fully synced\n");
- return;
- }
-
- CInv inv(MSG_MASTERNODE_PING, GetHash());
- connman.RelayInv(inv);
-}
-
-std::string CMasternodePing::GetSentinelString() const
-{
- return nSentinelVersion > DEFAULT_SENTINEL_VERSION ? SafeIntVersionToString(nSentinelVersion) : "Unknown";
-}
-
-std::string CMasternodePing::GetDaemonString() const
-{
- return nDaemonVersion > DEFAULT_DAEMON_VERSION ? FormatVersion(nDaemonVersion) : "Unknown";
-}
-
-void CMasternode::AddGovernanceVote(uint256 nGovernanceObjectHash)
-{
- // Insert a zero value, or not. Then increment the value regardless. This
- // ensures the value is in the map.
- const auto& pair = mapGovernanceObjectsVotedOn.emplace(nGovernanceObjectHash, 0);
- pair.first->second++;
-}
-
-void CMasternode::RemoveGovernanceObject(uint256 nGovernanceObjectHash)
-{
- // Whether or not the govobj hash exists in the map first is irrelevant.
- mapGovernanceObjectsVotedOn.erase(nGovernanceObjectHash);
-}
-
-/**
-* FLAG GOVERNANCE ITEMS AS DIRTY
-*
-* - When masternode come and go on the network, we must flag the items they voted on to recalc it's cached flags
-*
-*/
-void CMasternode::FlagGovernanceItemsAsDirty()
-{
- for (auto& govObjHashPair : mapGovernanceObjectsVotedOn) {
- mnodeman.AddDirtyGovernanceObjectHash(govObjHashPair.first);
- }
-}
diff --git a/src/masternode.h b/src/masternode.h
deleted file mode 100644
index 81e396d07eae..000000000000
--- a/src/masternode.h
+++ /dev/null
@@ -1,467 +0,0 @@
-// Copyright (c) 2014-2017 The Dash Core developers
-// Distributed under the MIT/X11 software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#ifndef MASTERNODE_H
-#define MASTERNODE_H
-
-#include "key.h"
-#include "validation.h"
-#include "spork.h"
-#include "bls/bls.h"
-
-#include "evo/deterministicmns.h"
-
-class CMasternode;
-class CMasternodeBroadcast;
-class CConnman;
-
-static const int MASTERNODE_CHECK_SECONDS = 5;
-static const int MASTERNODE_MIN_MNB_SECONDS = 5 * 60;
-static const int MASTERNODE_MIN_MNP_SECONDS = 10 * 60;
-static const int MASTERNODE_SENTINEL_PING_MAX_SECONDS = 60 * 60;
-static const int MASTERNODE_EXPIRATION_SECONDS = 120 * 60;
-static const int MASTERNODE_NEW_START_REQUIRED_SECONDS = 180 * 60;
-
-static const int MASTERNODE_POSE_BAN_MAX_SCORE = 5;
-static const int MASTERNODE_MAX_MIXING_TXES = 5;
-
-//
-// The Masternode Ping Class : Contains a different serialize method for sending pings from masternodes throughout the network
-//
-
-// sentinel version before implementation of nSentinelVersion in CMasternodePing
-#define DEFAULT_SENTINEL_VERSION 0x010001
-// daemon version before implementation of nDaemonVersion in CMasternodePing
-#define DEFAULT_DAEMON_VERSION 120200
-
-class CMasternodePing
-{
-public:
- COutPoint masternodeOutpoint{};
- uint256 blockHash{};
- int64_t sigTime{}; //mnb message times
- std::vector vchSig{};
- bool fSentinelIsCurrent = false; // true if last sentinel ping was current
- // MSB is always 0, other 3 bits corresponds to x.x.x version scheme
- uint32_t nSentinelVersion{DEFAULT_SENTINEL_VERSION};
- uint32_t nDaemonVersion{DEFAULT_DAEMON_VERSION};
-
- CMasternodePing() = default;
-
- CMasternodePing(const COutPoint& outpoint);
-
- ADD_SERIALIZE_METHODS;
-
- template
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(masternodeOutpoint);
- READWRITE(blockHash);
- READWRITE(sigTime);
- if (!(s.GetType() & SER_GETHASH)) {
- READWRITE(vchSig);
- }
- READWRITE(fSentinelIsCurrent);
- READWRITE(nSentinelVersion);
- READWRITE(nDaemonVersion);
- }
-
- uint256 GetHash() const;
- uint256 GetSignatureHash() const;
-
- bool IsExpired() const { return GetAdjustedTime() - sigTime > MASTERNODE_NEW_START_REQUIRED_SECONDS; }
-
- bool Sign(const CKey& keyMasternode, const CKeyID& keyIDOperator);
- bool CheckSignature(CKeyID& keyIDOperator, int &nDos) const;
- bool SimpleCheck(int& nDos);
- bool CheckAndUpdate(CMasternode* pmn, bool fFromNewBroadcast, int& nDos, CConnman& connman);
- void Relay(CConnman& connman);
-
- std::string GetSentinelString() const;
- std::string GetDaemonString() const;
-
- explicit operator bool() const;
-};
-
-inline bool operator==(const CMasternodePing& a, const CMasternodePing& b)
-{
- return a.masternodeOutpoint == b.masternodeOutpoint && a.blockHash == b.blockHash;
-}
-inline bool operator!=(const CMasternodePing& a, const CMasternodePing& b)
-{
- return !(a == b);
-}
-inline CMasternodePing::operator bool() const
-{
- return *this != CMasternodePing();
-}
-
-struct masternode_info_t
-{
- // Note: all these constructors can be removed once C++14 is enabled.
- // (in C++11 the member initializers wrongly disqualify this as an aggregate)
- masternode_info_t() = default;
- masternode_info_t(masternode_info_t const&) = default;
-
- masternode_info_t(int activeState, int protoVer, int64_t sTime) :
- nActiveState{activeState}, nProtocolVersion{protoVer}, sigTime{sTime} {}
-
- // only called when the network is in legacy MN list mode
- masternode_info_t(int activeState, int protoVer, int64_t sTime,
- COutPoint const& outpnt, CService const& addr,
- CPubKey const& pkCollAddr, CPubKey const& pkMN) :
- nActiveState{activeState}, nProtocolVersion{protoVer}, sigTime{sTime},
- outpoint{outpnt}, addr{addr},
- pubKeyCollateralAddress{pkCollAddr}, pubKeyMasternode{pkMN}, keyIDCollateralAddress{pkCollAddr.GetID()}, keyIDOwner{pkMN.GetID()}, legacyKeyIDOperator{pkMN.GetID()}, keyIDVoting{pkMN.GetID()} {}
-
- // only called when the network is in deterministic MN list mode
- masternode_info_t(int activeState, int protoVer, int64_t sTime,
- COutPoint const& outpnt, CService const& addr,
- CKeyID const& pkCollAddr, CKeyID const& pkOwner, CBLSPublicKey const& pkOperator, CKeyID const& pkVoting) :
- nActiveState{activeState}, nProtocolVersion{protoVer}, sigTime{sTime},
- outpoint{outpnt}, addr{addr},
- pubKeyCollateralAddress{}, pubKeyMasternode{}, keyIDCollateralAddress{pkCollAddr}, keyIDOwner{pkOwner}, blsPubKeyOperator{pkOperator}, keyIDVoting{pkVoting} {}
-
- int nActiveState = 0;
- int nProtocolVersion = 0;
- int64_t sigTime = 0; //mnb message time
-
- COutPoint outpoint{};
- CService addr{};
- CPubKey pubKeyCollateralAddress{}; // this will be invalid/unset when the network switches to deterministic MNs (luckely it's only important for the broadcast hash)
- CPubKey pubKeyMasternode{}; // this will be invalid/unset when the network switches to deterministic MNs (luckely it's only important for the broadcast hash)
- CKeyID keyIDCollateralAddress{}; // this is only used in compatibility code and won't be used when spork15 gets activated
- CKeyID keyIDOwner{};
- CKeyID legacyKeyIDOperator{};
- CBLSPublicKey blsPubKeyOperator;
- CKeyID keyIDVoting{};
-
- int64_t nLastDsq = 0; //the dsq count from the last dsq broadcast of this node
- int64_t nTimeLastChecked = 0;
- int64_t nTimeLastPaid = 0;
- int64_t nTimeLastPing = 0; //* not in CMN
- bool fInfoValid = false; //* not in CMN
-};
-
-//
-// The Masternode Class. For managing the Darksend process. It contains the input of the 1000DRK, signature to prove
-// it's the one who own that ip address and code for calculating the payment election.
-//
-class CMasternode : public masternode_info_t
-{
-private:
- // critical section to protect the inner data structures
- mutable CCriticalSection cs;
-
-public:
- enum state {
- MASTERNODE_PRE_ENABLED,
- MASTERNODE_ENABLED,
- MASTERNODE_EXPIRED,
- MASTERNODE_OUTPOINT_SPENT,
- MASTERNODE_UPDATE_REQUIRED,
- MASTERNODE_SENTINEL_PING_EXPIRED,
- MASTERNODE_NEW_START_REQUIRED,
- MASTERNODE_POSE_BAN
- };
-
- enum CollateralStatus {
- COLLATERAL_OK,
- COLLATERAL_UTXO_NOT_FOUND,
- COLLATERAL_INVALID_AMOUNT,
- COLLATERAL_INVALID_PUBKEY,
- };
-
-
- CMasternodePing lastPing{};
- std::vector vchSig{};
-
- uint256 nCollateralMinConfBlockHash{};
- int nBlockLastPaid{};
- int nPoSeBanScore{};
- int nPoSeBanHeight{};
- int nMixingTxCount{};
- bool fUnitTest = false;
-
- // KEEP TRACK OF GOVERNANCE ITEMS EACH MASTERNODE HAS VOTE UPON FOR RECALCULATION
- std::map mapGovernanceObjectsVotedOn;
-
- CMasternode();
- CMasternode(const CMasternode& other);
- CMasternode(const CMasternodeBroadcast& mnb);
- CMasternode(CService addrNew, COutPoint outpointNew, CPubKey pubKeyCollateralAddressNew, CPubKey pubKeyMasternodeNew, int nProtocolVersionIn);
- CMasternode(const uint256 &proTxHash, const CDeterministicMNCPtr& dmn);
-
- ADD_SERIALIZE_METHODS;
-
- template
- inline void SerializationOp(Stream& s, Operation ser_action) {
- LOCK(cs);
- READWRITE(outpoint);
- READWRITE(addr);
- READWRITE(pubKeyCollateralAddress);
- READWRITE(pubKeyMasternode);
- READWRITE(keyIDCollateralAddress);
- READWRITE(keyIDOwner);
- READWRITE(legacyKeyIDOperator);
- READWRITE(blsPubKeyOperator);
- READWRITE(keyIDVoting);
- READWRITE(lastPing);
- READWRITE(vchSig);
- READWRITE(sigTime);
- READWRITE(nLastDsq);
- READWRITE(nTimeLastChecked);
- READWRITE(nTimeLastPaid);
- READWRITE(nActiveState);
- READWRITE(nCollateralMinConfBlockHash);
- READWRITE(nBlockLastPaid);
- READWRITE(nProtocolVersion);
- READWRITE(nPoSeBanScore);
- READWRITE(nPoSeBanHeight);
- READWRITE(nMixingTxCount);
- READWRITE(fUnitTest);
- READWRITE(mapGovernanceObjectsVotedOn);
- }
-
- // CALCULATE A RANK AGAINST OF GIVEN BLOCK
- arith_uint256 CalculateScore(const uint256& blockHash) const;
-
- bool UpdateFromNewBroadcast(CMasternodeBroadcast& mnb, CConnman& connman);
-
- static CollateralStatus CheckCollateral(const COutPoint& outpoint, const CKeyID& keyID);
- static CollateralStatus CheckCollateral(const COutPoint& outpoint, const CKeyID& keyID, int& nHeightRet);
- void Check(bool fForce = false);
-
- bool IsBroadcastedWithin(int nSeconds) { return GetAdjustedTime() - sigTime < nSeconds; }
-
- bool IsPingedWithin(int nSeconds, int64_t nTimeToCheckAt = -1)
- {
- if(!lastPing) return false;
-
- if(nTimeToCheckAt == -1) {
- nTimeToCheckAt = GetAdjustedTime();
- }
- return nTimeToCheckAt - lastPing.sigTime < nSeconds;
- }
-
- bool IsEnabled() const { return nActiveState == MASTERNODE_ENABLED; }
- bool IsPreEnabled() const { return nActiveState == MASTERNODE_PRE_ENABLED; }
- bool IsPoSeBanned() const { return nActiveState == MASTERNODE_POSE_BAN; }
- // NOTE: this one relies on nPoSeBanScore, not on nActiveState as everything else here
- bool IsPoSeVerified() const { return nPoSeBanScore <= -MASTERNODE_POSE_BAN_MAX_SCORE; }
- bool IsExpired() const { return nActiveState == MASTERNODE_EXPIRED; }
- bool IsOutpointSpent() const { return nActiveState == MASTERNODE_OUTPOINT_SPENT; }
- bool IsUpdateRequired() const { return nActiveState == MASTERNODE_UPDATE_REQUIRED; }
- bool IsSentinelPingExpired() const { return nActiveState == MASTERNODE_SENTINEL_PING_EXPIRED; }
- bool IsNewStartRequired() const { return nActiveState == MASTERNODE_NEW_START_REQUIRED; }
-
- static bool IsValidStateForAutoStart(int nActiveStateIn)
- {
- return nActiveStateIn == MASTERNODE_ENABLED ||
- nActiveStateIn == MASTERNODE_PRE_ENABLED ||
- nActiveStateIn == MASTERNODE_EXPIRED ||
- nActiveStateIn == MASTERNODE_SENTINEL_PING_EXPIRED;
- }
-
- bool IsValidForPayment() const
- {
- if(nActiveState == MASTERNODE_ENABLED) {
- return true;
- }
- if(!sporkManager.IsSporkActive(SPORK_14_REQUIRE_SENTINEL_FLAG) &&
- (nActiveState == MASTERNODE_SENTINEL_PING_EXPIRED)) {
- return true;
- }
-
- return false;
- }
-
- bool IsValidForMixingTxes() const
- {
- return nMixingTxCount <= MASTERNODE_MAX_MIXING_TXES;
- }
-
- bool IsValidNetAddr();
- static bool IsValidNetAddr(CService addrIn);
-
- void IncreasePoSeBanScore() { if(nPoSeBanScore < MASTERNODE_POSE_BAN_MAX_SCORE) nPoSeBanScore++; }
- void DecreasePoSeBanScore() { if(nPoSeBanScore > -MASTERNODE_POSE_BAN_MAX_SCORE) nPoSeBanScore--; }
- void PoSeBan() { nPoSeBanScore = MASTERNODE_POSE_BAN_MAX_SCORE; }
-
- masternode_info_t GetInfo() const;
-
- static std::string StateToString(int nStateIn);
- std::string GetStateString() const;
- std::string GetStatus() const;
-
- int GetLastPaidTime() const { return nTimeLastPaid; }
- int GetLastPaidBlock() const { return nBlockLastPaid; }
- void UpdateLastPaid(const CBlockIndex *pindex, int nMaxBlocksToScanBack);
-
- // KEEP TRACK OF EACH GOVERNANCE ITEM INCASE THIS NODE GOES OFFLINE, SO WE CAN RECALC THEIR STATUS
- void AddGovernanceVote(uint256 nGovernanceObjectHash);
- // RECALCULATE CACHED STATUS FLAGS FOR ALL AFFECTED OBJECTS
- void FlagGovernanceItemsAsDirty();
-
- void RemoveGovernanceObject(uint256 nGovernanceObjectHash);
-
- CMasternode& operator=(CMasternode const& from)
- {
- static_cast(*this)=from;
- lastPing = from.lastPing;
- vchSig = from.vchSig;
- nCollateralMinConfBlockHash = from.nCollateralMinConfBlockHash;
- nBlockLastPaid = from.nBlockLastPaid;
- nPoSeBanScore = from.nPoSeBanScore;
- nPoSeBanHeight = from.nPoSeBanHeight;
- nMixingTxCount = from.nMixingTxCount;
- fUnitTest = from.fUnitTest;
- mapGovernanceObjectsVotedOn = from.mapGovernanceObjectsVotedOn;
- return *this;
- }
-};
-
-inline bool operator==(const CMasternode& a, const CMasternode& b)
-{
- return a.outpoint == b.outpoint;
-}
-inline bool operator!=(const CMasternode& a, const CMasternode& b)
-{
- return !(a.outpoint == b.outpoint);
-}
-
-
-//
-// The Masternode Broadcast Class : Contains a different serialize method for sending masternodes through the network
-//
-
-class CMasternodeBroadcast : public CMasternode
-{
-public:
-
- bool fRecovery;
-
- CMasternodeBroadcast() : CMasternode(), fRecovery(false) {}
- CMasternodeBroadcast(const CMasternode& mn) : CMasternode(mn), fRecovery(false) {}
- CMasternodeBroadcast(CService addrNew, COutPoint outpointNew, CPubKey pubKeyCollateralAddressNew, CPubKey pubKeyMasternodeNew, int nProtocolVersionIn) :
- CMasternode(addrNew, outpointNew, pubKeyCollateralAddressNew, pubKeyMasternodeNew, nProtocolVersionIn), fRecovery(false) {}
-
- ADD_SERIALIZE_METHODS;
-
- template
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(outpoint);
- READWRITE(addr);
- READWRITE(pubKeyCollateralAddress);
- READWRITE(pubKeyMasternode);
- if (!(s.GetType() & SER_GETHASH)) {
- READWRITE(vchSig);
- }
- READWRITE(sigTime);
- READWRITE(nProtocolVersion);
- if (!(s.GetType() & SER_GETHASH)) {
- READWRITE(lastPing);
- }
-
- if (ser_action.ForRead()) {
- keyIDCollateralAddress = pubKeyCollateralAddress.GetID();
- keyIDOwner = pubKeyMasternode.GetID();
- legacyKeyIDOperator = pubKeyMasternode.GetID();
- keyIDVoting = pubKeyMasternode.GetID();
- }
- }
-
- uint256 GetHash() const;
- uint256 GetSignatureHash() const;
-
- /// Create Masternode broadcast, needs to be relayed manually after that
- static bool Create(const COutPoint& outpoint, const CService& service, const CKey& keyCollateralAddressNew, const CPubKey& pubKeyCollateralAddressNew, const CKey& keyMasternodeNew, const CPubKey& pubKeyMasternodeNew, std::string &strErrorRet, CMasternodeBroadcast &mnbRet);
- static bool Create(const std::string& strService, const std::string& strKey, const std::string& strTxHash, const std::string& strOutputIndex, std::string& strErrorRet, CMasternodeBroadcast &mnbRet, bool fOffline = false);
-
- bool SimpleCheck(int& nDos);
- bool Update(CMasternode* pmn, int& nDos, CConnman& connman);
- bool CheckOutpoint(int& nDos);
-
- bool Sign(const CKey& keyCollateralAddress);
- bool CheckSignature(int& nDos) const;
- void Relay(CConnman& connman) const;
-};
-
-class CMasternodeVerification
-{
-public:
- COutPoint masternodeOutpoint1{};
- COutPoint masternodeOutpoint2{};
- CService addr{};
- int nonce{};
- int nBlockHeight{};
- std::vector vchSig1{};
- std::vector vchSig2{};
-
- CMasternodeVerification() = default;
-
- CMasternodeVerification(CService addr, int nonce, int nBlockHeight) :
- addr(addr),
- nonce(nonce),
- nBlockHeight(nBlockHeight)
- {}
-
- ADD_SERIALIZE_METHODS;
-
- template
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(masternodeOutpoint1);
- READWRITE(masternodeOutpoint2);
- READWRITE(addr);
- READWRITE(nonce);
- READWRITE(nBlockHeight);
- READWRITE(vchSig1);
- READWRITE(vchSig2);
- }
-
- uint256 GetHash() const
- {
- // Note: doesn't match serialization
-
- CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
- // adding dummy values here to match old hashing format
- ss << masternodeOutpoint1 << uint8_t{} << 0xffffffff;
- ss << masternodeOutpoint2 << uint8_t{} << 0xffffffff;
- ss << addr;
- ss << nonce;
- ss << nBlockHeight;
- return ss.GetHash();
- }
-
- uint256 GetSignatureHash1(const uint256& blockHash) const
- {
- // Note: doesn't match serialization
-
- CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
- ss << addr;
- ss << nonce;
- ss << blockHash;
- return ss.GetHash();
- }
-
- uint256 GetSignatureHash2(const uint256& blockHash) const
- {
- // Note: doesn't match serialization
-
- CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
- ss << masternodeOutpoint1;
- ss << masternodeOutpoint2;
- ss << addr;
- ss << nonce;
- ss << blockHash;
- return ss.GetHash();
- }
-
- void Relay() const
- {
- CInv inv(MSG_MASTERNODE_VERIFY, GetHash());
- g_connman->RelayInv(inv);
- }
-};
-
-#endif
diff --git a/src/masternodeconfig.cpp b/src/masternodeconfig.cpp
deleted file mode 100644
index 0e2e67be796a..000000000000
--- a/src/masternodeconfig.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-
-#include "netbase.h"
-#include "masternodeconfig.h"
-#include "util.h"
-#include "chainparams.h"
-
-#include
-#include
-
-CMasternodeConfig masternodeConfig;
-
-void CMasternodeConfig::add(const std::string& alias, const std::string& ip, const std::string& privKey, const std::string& txHash, const std::string& outputIndex) {
- CMasternodeEntry cme(alias, ip, privKey, txHash, outputIndex);
- entries.push_back(cme);
-}
-
-bool CMasternodeConfig::read(std::string& strErrRet) {
- int linenumber = 1;
- boost::filesystem::path pathMasternodeConfigFile = GetMasternodeConfigFile();
- boost::filesystem::ifstream streamConfig(pathMasternodeConfigFile);
-
- if (!streamConfig.good()) {
- FILE* configFile = fopen(pathMasternodeConfigFile.string().c_str(), "a");
- if (configFile != nullptr) {
- std::string strHeader = "# Masternode config file\n"
- "# Format: alias IP:port masternodeprivkey collateral_output_txid collateral_output_index\n"
- "# Example: mn1 127.0.0.2:19999 93HaYBVUCYjEMeeH1Y4sBGLALQZE1Yc1K64xiqgX37tGBDQL8Xg 2bcd3c84c84f87eaa86e4e56834c92927a07f9e18718810b92e0d0324456a67c 0\n";
- fwrite(strHeader.c_str(), std::strlen(strHeader.c_str()), 1, configFile);
- fclose(configFile);
- }
- return true; // Nothing to read, so just return
- }
-
- for(std::string line; std::getline(streamConfig, line); linenumber++)
- {
- if(line.empty()) continue;
-
- std::istringstream iss(line);
- std::string comment, alias, ip, privKey, txHash, outputIndex;
-
- if (iss >> comment) {
- if(comment.at(0) == '#') continue;
- iss.str(line);
- iss.clear();
- }
-
- if (!(iss >> alias >> ip >> privKey >> txHash >> outputIndex)) {
- iss.str(line);
- iss.clear();
- if (!(iss >> alias >> ip >> privKey >> txHash >> outputIndex)) {
- strErrRet = _("Could not parse masternode.conf") + "\n" +
- strprintf(_("Line: %d"), linenumber) + "\n\"" + line + "\"";
- streamConfig.close();
- return false;
- }
- }
-
- int port = 0;
- std::string hostname = "";
- SplitHostPort(ip, port, hostname);
- if(port == 0 || hostname == "") {
- strErrRet = _("Failed to parse host:port string") + "\n"+
- strprintf(_("Line: %d"), linenumber) + "\n\"" + line + "\"";
- streamConfig.close();
- return false;
- }
- int mainnetDefaultPort = Params(CBaseChainParams::MAIN).GetDefaultPort();
- if(Params().NetworkIDString() == CBaseChainParams::MAIN) {
- if(port != mainnetDefaultPort) {
- strErrRet = _("Invalid port detected in masternode.conf") + "\n" +
- strprintf(_("Port: %d"), port) + "\n" +
- strprintf(_("Line: %d"), linenumber) + "\n\"" + line + "\"" + "\n" +
- strprintf(_("(must be %d for mainnet)"), mainnetDefaultPort);
- streamConfig.close();
- return false;
- }
- } else if(port == mainnetDefaultPort) {
- strErrRet = _("Invalid port detected in masternode.conf") + "\n" +
- strprintf(_("Line: %d"), linenumber) + "\n\"" + line + "\"" + "\n" +
- strprintf(_("(%d could be used only on mainnet)"), mainnetDefaultPort);
- streamConfig.close();
- return false;
- }
-
-
- add(alias, ip, privKey, txHash, outputIndex);
- }
-
- streamConfig.close();
- return true;
-}
diff --git a/src/masternodeconfig.h b/src/masternodeconfig.h
deleted file mode 100644
index 7d978d9dc7d4..000000000000
--- a/src/masternodeconfig.h
+++ /dev/null
@@ -1,79 +0,0 @@
-
-// Copyright (c) 2014-2017 The Dash Core developers
-// Distributed under the MIT/X11 software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#ifndef SRC_MASTERNODECONFIG_H_
-#define SRC_MASTERNODECONFIG_H_
-
-class CMasternodeConfig;
-extern CMasternodeConfig masternodeConfig;
-
-class CMasternodeConfig
-{
-
-public:
-
- class CMasternodeEntry {
-
- private:
- std::string alias;
- std::string ip;
- std::string privKey;
- std::string txHash;
- std::string outputIndex;
- public:
-
- CMasternodeEntry(const std::string& alias, const std::string& ip, const std::string& privKey, const std::string& txHash, const std::string& outputIndex) {
- this->alias = alias;
- this->ip = ip;
- this->privKey = privKey;
- this->txHash = txHash;
- this->outputIndex = outputIndex;
- }
-
- const std::string& getAlias() const {
- return alias;
- }
-
- const std::string& getOutputIndex() const {
- return outputIndex;
- }
-
- const std::string& getPrivKey() const {
- return privKey;
- }
-
- const std::string& getTxHash() const {
- return txHash;
- }
-
- const std::string& getIp() const {
- return ip;
- }
- };
-
- CMasternodeConfig() {
- entries = std::vector();
- }
-
- void clear();
- bool read(std::string& strErrRet);
- void add(const std::string& alias, const std::string& ip, const std::string& privKey, const std::string& txHash, const std::string& outputIndex);
-
- std::vector& getEntries() {
- return entries;
- }
-
- int getCount() {
- return (int)entries.size();
- }
-
-private:
- std::vector entries;
-
-
-};
-
-
-#endif /* SRC_MASTERNODECONFIG_H_ */
diff --git a/src/masternodeman.cpp b/src/masternodeman.cpp
deleted file mode 100644
index b118b3839f54..000000000000
--- a/src/masternodeman.cpp
+++ /dev/null
@@ -1,2023 +0,0 @@
-// Copyright (c) 2014-2017 The Dash Core developers
-// Distributed under the MIT/X11 software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#include "activemasternode.h"
-#include "addrman.h"
-#include "alert.h"
-#include "clientversion.h"
-#include "init.h"
-#include "governance.h"
-#include "masternode-payments.h"
-#include "masternode-sync.h"
-#include "masternodeman.h"
-#include "messagesigner.h"
-#include "netfulfilledman.h"
-#include "netmessagemaker.h"
-#ifdef ENABLE_WALLET
-#include "privatesend-client.h"
-#endif // ENABLE_WALLET
-#include "script/standard.h"
-#include "ui_interface.h"
-#include "util.h"
-#include "warnings.h"
-
-#include "evo/deterministicmns.h"
-#include "evo/providertx.h"
-
-/** Masternode manager */
-CMasternodeMan mnodeman;
-
-const std::string CMasternodeMan::SERIALIZATION_VERSION_STRING = "CMasternodeMan-Version-12";
-const int CMasternodeMan::LAST_PAID_SCAN_BLOCKS = 100;
-
-struct CompareLastPaidBlock
-{
- bool operator()(const std::pair& t1,
- const std::pair& t2) const
- {
- return (t1.first != t2.first) ? (t1.first < t2.first) : (t1.second->outpoint < t2.second->outpoint);
- }
-};
-
-struct CompareScoreMN
-{
- bool operator()(const std::pair& t1,
- const std::pair& t2) const
- {
- return (t1.first != t2.first) ? (t1.first < t2.first) : (t1.second->outpoint < t2.second->outpoint);
- }
-};
-
-struct CompareByAddr
-
-{
- bool operator()(const CMasternode* t1,
- const CMasternode* t2) const
- {
- return t1->addr < t2->addr;
- }
-};
-
-CMasternodeMan::CMasternodeMan():
- cs(),
- mapMasternodes(),
- mAskedUsForMasternodeList(),
- mWeAskedForMasternodeList(),
- mWeAskedForMasternodeListEntry(),
- mWeAskedForVerification(),
- mMnbRecoveryRequests(),
- mMnbRecoveryGoodReplies(),
- listScheduledMnbRequestConnections(),
- fMasternodesAdded(false),
- fMasternodesRemoved(false),
- vecDirtyGovernanceObjectHashes(),
- nLastSentinelPingTime(0),
- mapSeenMasternodeBroadcast(),
- mapSeenMasternodePing(),
- nDsqCount(0)
-{}
-
-bool CMasternodeMan::Add(CMasternode &mn)
-{
- LOCK(cs);
-
- if (deterministicMNManager->IsDeterministicMNsSporkActive())
- return false;
-
- if (Has(mn.outpoint)) return false;
-
- LogPrint("masternode", "CMasternodeMan::Add -- Adding new Masternode: addr=%s, %i now\n", mn.addr.ToString(), size() + 1);
- mapMasternodes[mn.outpoint] = mn;
- fMasternodesAdded = true;
- return true;
-}
-
-void CMasternodeMan::AskForMN(CNode* pnode, const COutPoint& outpoint, CConnman& connman)
-{
- if(!pnode) return;
-
- CNetMsgMaker msgMaker(pnode->GetSendVersion());
- LOCK(cs);
-
- if (deterministicMNManager->IsDeterministicMNsSporkActive())
- return;
-
- CService addrSquashed = Params().AllowMultiplePorts() ? (CService)pnode->addr : CService(pnode->addr, 0);
- auto it1 = mWeAskedForMasternodeListEntry.find(outpoint);
- if (it1 != mWeAskedForMasternodeListEntry.end()) {
- auto it2 = it1->second.find(addrSquashed);
- if (it2 != it1->second.end()) {
- if (GetTime() < it2->second) {
- // we've asked recently, should not repeat too often or we could get banned
- return;
- }
- // we asked this node for this outpoint but it's ok to ask again already
- LogPrintf("CMasternodeMan::AskForMN -- Asking same peer %s for missing masternode entry again: %s\n", addrSquashed.ToString(), outpoint.ToStringShort());
- } else {
- // we already asked for this outpoint but not this node
- LogPrintf("CMasternodeMan::AskForMN -- Asking new peer %s for missing masternode entry: %s\n", addrSquashed.ToString(), outpoint.ToStringShort());
- }
- } else {
- // we never asked any node for this outpoint
- LogPrintf("CMasternodeMan::AskForMN -- Asking peer %s for missing masternode entry for the first time: %s\n", addrSquashed.ToString(), outpoint.ToStringShort());
- }
- mWeAskedForMasternodeListEntry[outpoint][addrSquashed] = GetTime() + DSEG_UPDATE_SECONDS;
-
- connman.PushMessage(pnode, msgMaker.Make(NetMsgType::DSEG, outpoint));
-}
-
-bool CMasternodeMan::AllowMixing(const COutPoint &outpoint)
-{
- LOCK(cs);
- CMasternode* pmn = Find(outpoint);
- if (!pmn) {
- return false;
- }
- nDsqCount++;
- pmn->nLastDsq = nDsqCount;
- pmn->nMixingTxCount = 0;
-
- return true;
-}
-
-bool CMasternodeMan::DisallowMixing(const COutPoint &outpoint)
-{
- LOCK(cs);
- CMasternode* pmn = Find(outpoint);
- if (!pmn) {
- return false;
- }
- pmn->nMixingTxCount++;
-
- return true;
-}
-
-bool CMasternodeMan::PoSeBan(const COutPoint &outpoint)
-{
- LOCK(cs);
-
- if (deterministicMNManager->IsDeterministicMNsSporkActive())
- return true;
-
- CMasternode* pmn = Find(outpoint);
- if (!pmn) {
- return false;
- }
- pmn->PoSeBan();
-
- return true;
-}
-
-void CMasternodeMan::Check()
-{
- LOCK2(cs_main, cs);
-
- if (deterministicMNManager->IsDeterministicMNsSporkActive())
- return;
-
- for (auto& mnpair : mapMasternodes) {
- // NOTE: internally it checks only every MASTERNODE_CHECK_SECONDS seconds
- // since the last time, so expect some MNs to skip this
- mnpair.second.Check();
- }
-}
-
-void CMasternodeMan::CheckAndRemove(CConnman& connman)
-{
- if (deterministicMNManager->IsDeterministicMNsSporkActive())
- return;
-
- if(!masternodeSync.IsMasternodeListSynced()) return;
-
- LogPrintf("CMasternodeMan::CheckAndRemove\n");
-
- {
- // Need LOCK2 here to ensure consistent locking order because code below locks cs_main
- // in CheckMnbAndUpdateMasternodeList()
- LOCK2(cs_main, cs);
-
- Check();
-
- // Remove spent masternodes, prepare structures and make requests to reasure the state of inactive ones
- rank_pair_vec_t vecMasternodeRanks;
- // ask for up to MNB_RECOVERY_MAX_ASK_ENTRIES masternode entries at a time
- int nAskForMnbRecovery = MNB_RECOVERY_MAX_ASK_ENTRIES;
- std::map::iterator it = mapMasternodes.begin();
- while (it != mapMasternodes.end()) {
- CMasternodeBroadcast mnb = CMasternodeBroadcast(it->second);
- uint256 hash = mnb.GetHash();
- // If collateral was spent ...
- if (it->second.IsOutpointSpent()) {
- LogPrint("masternode", "CMasternodeMan::CheckAndRemove -- Removing Masternode: %s addr=%s %i now\n", it->second.GetStateString(), it->second.addr.ToString(), size() - 1);
-
- // erase all of the broadcasts we've seen from this txin, ...
- mapSeenMasternodeBroadcast.erase(hash);
- mWeAskedForMasternodeListEntry.erase(it->first);
-
- // and finally remove it from the list
- it->second.FlagGovernanceItemsAsDirty();
- mapMasternodes.erase(it++);
- fMasternodesRemoved = true;
- } else {
- bool fAsk = (nAskForMnbRecovery > 0) &&
- masternodeSync.IsSynced() &&
- it->second.IsNewStartRequired() &&
- !IsMnbRecoveryRequested(hash) &&
- !IsArgSet("-connect");
- if(fAsk) {
- // this mn is in a non-recoverable state and we haven't asked other nodes yet
- std::set setRequested;
- // calulate only once and only when it's needed
- if(vecMasternodeRanks.empty()) {
- int nRandomBlockHeight = GetRandInt(nCachedBlockHeight);
- GetMasternodeRanks(vecMasternodeRanks, nRandomBlockHeight);
- }
- bool fAskedForMnbRecovery = false;
- // ask first MNB_RECOVERY_QUORUM_TOTAL masternodes we can connect to and we haven't asked recently
- for(int i = 0; setRequested.size() < MNB_RECOVERY_QUORUM_TOTAL && i < (int)vecMasternodeRanks.size(); i++) {
- // avoid banning
- if(mWeAskedForMasternodeListEntry.count(it->first) && mWeAskedForMasternodeListEntry[it->first].count(vecMasternodeRanks[i].second.addr)) continue;
- // didn't ask recently, ok to ask now
- CService addr = vecMasternodeRanks[i].second.addr;
- setRequested.insert(addr);
- listScheduledMnbRequestConnections.push_back(std::make_pair(addr, hash));
- fAskedForMnbRecovery = true;
- }
- if(fAskedForMnbRecovery) {
- LogPrint("masternode", "CMasternodeMan::CheckAndRemove -- Recovery initiated, masternode=%s\n", it->first.ToStringShort());
- nAskForMnbRecovery--;
- }
- // wait for mnb recovery replies for MNB_RECOVERY_WAIT_SECONDS seconds
- mMnbRecoveryRequests[hash] = std::make_pair(GetTime() + MNB_RECOVERY_WAIT_SECONDS, setRequested);
- }
- ++it;
- }
- }
-
- // proces replies for MASTERNODE_NEW_START_REQUIRED masternodes
- LogPrint("masternode", "CMasternodeMan::CheckAndRemove -- mMnbRecoveryGoodReplies size=%d\n", (int)mMnbRecoveryGoodReplies.size());
- std::map >::iterator itMnbReplies = mMnbRecoveryGoodReplies.begin();
- while(itMnbReplies != mMnbRecoveryGoodReplies.end()){
- if(mMnbRecoveryRequests[itMnbReplies->first].first < GetTime()) {
- // all nodes we asked should have replied now
- if(itMnbReplies->second.size() >= MNB_RECOVERY_QUORUM_REQUIRED) {
- // majority of nodes we asked agrees that this mn doesn't require new mnb, reprocess one of new mnbs
- LogPrint("masternode", "CMasternodeMan::CheckAndRemove -- reprocessing mnb, masternode=%s\n", itMnbReplies->second[0].outpoint.ToStringShort());
- // mapSeenMasternodeBroadcast.erase(itMnbReplies->first);
- int nDos;
- itMnbReplies->second[0].fRecovery = true;
- CheckMnbAndUpdateMasternodeList(nullptr, itMnbReplies->second[0], nDos, connman);
- }
- LogPrint("masternode", "CMasternodeMan::CheckAndRemove -- removing mnb recovery reply, masternode=%s, size=%d\n", itMnbReplies->second[0].outpoint.ToStringShort(), (int)itMnbReplies->second.size());
- mMnbRecoveryGoodReplies.erase(itMnbReplies++);
- } else {
- ++itMnbReplies;
- }
- }
- }
- {
- // no need for cm_main below
- LOCK(cs);
-
- auto itMnbRequest = mMnbRecoveryRequests.begin();
- while(itMnbRequest != mMnbRecoveryRequests.end()){
- // Allow this mnb to be re-verified again after MNB_RECOVERY_RETRY_SECONDS seconds
- // if mn is still in MASTERNODE_NEW_START_REQUIRED state.
- if(GetTime() - itMnbRequest->second.first > MNB_RECOVERY_RETRY_SECONDS) {
- mMnbRecoveryRequests.erase(itMnbRequest++);
- } else {
- ++itMnbRequest;
- }
- }
-
- // check who's asked for the Masternode list
- auto it1 = mAskedUsForMasternodeList.begin();
- while(it1 != mAskedUsForMasternodeList.end()){
- if((*it1).second < GetTime()) {
- mAskedUsForMasternodeList.erase(it1++);
- } else {
- ++it1;
- }
- }
-
- // check who we asked for the Masternode list
- it1 = mWeAskedForMasternodeList.begin();
- while(it1 != mWeAskedForMasternodeList.end()){
- if((*it1).second < GetTime()){
- mWeAskedForMasternodeList.erase(it1++);
- } else {
- ++it1;
- }
- }
-
- // check which Masternodes we've asked for
- auto it2 = mWeAskedForMasternodeListEntry.begin();
- while(it2 != mWeAskedForMasternodeListEntry.end()){
- auto it3 = it2->second.begin();
- while(it3 != it2->second.end()){
- if(it3->second < GetTime()){
- it2->second.erase(it3++);
- } else {
- ++it3;
- }
- }
- if(it2->second.empty()) {
- mWeAskedForMasternodeListEntry.erase(it2++);
- } else {
- ++it2;
- }
- }
-
- auto it3 = mWeAskedForVerification.begin();
- while(it3 != mWeAskedForVerification.end()){
- if(it3->second.nBlockHeight < nCachedBlockHeight - MAX_POSE_BLOCKS) {
- mWeAskedForVerification.erase(it3++);
- } else {
- ++it3;
- }
- }
-
- // NOTE: do not expire mapSeenMasternodeBroadcast entries here, clean them on mnb updates!
-
- // remove expired mapSeenMasternodePing
- std::map::iterator it4 = mapSeenMasternodePing.begin();
- while(it4 != mapSeenMasternodePing.end()){
- if((*it4).second.IsExpired()) {
- LogPrint("masternode", "CMasternodeMan::CheckAndRemove -- Removing expired Masternode ping: hash=%s\n", (*it4).second.GetHash().ToString());
- mapSeenMasternodePing.erase(it4++);
- } else {
- ++it4;
- }
- }
-
- // remove expired mapSeenMasternodeVerification
- std::map::iterator itv2 = mapSeenMasternodeVerification.begin();
- while(itv2 != mapSeenMasternodeVerification.end()){
- if((*itv2).second.nBlockHeight < nCachedBlockHeight - MAX_POSE_BLOCKS){
- LogPrint("masternode", "CMasternodeMan::CheckAndRemove -- Removing expired Masternode verification: hash=%s\n", (*itv2).first.ToString());
- mapSeenMasternodeVerification.erase(itv2++);
- } else {
- ++itv2;
- }
- }
-
- LogPrintf("CMasternodeMan::CheckAndRemove -- %s\n", ToString());
- }
-
- if(fMasternodesRemoved) {
- NotifyMasternodeUpdates(connman);
- }
-}
-
-void CMasternodeMan::AddDeterministicMasternodes()
-{
- if (!deterministicMNManager->IsDeterministicMNsSporkActive())
- return;
-
- bool added = false;
- {
- LOCK(cs);
- unsigned int oldMnCount = mapMasternodes.size();
-
- auto mnList = deterministicMNManager->GetListAtChainTip();
- mnList.ForEachMN(true, [this](const CDeterministicMNCPtr& dmn) {
- // call Find() on each deterministic MN to force creation of CMasternode object
- auto mn = Find(dmn->collateralOutpoint);
- assert(mn);
-
- // make sure we use the splitted keys from now on
- mn->keyIDOwner = dmn->pdmnState->keyIDOwner;
- mn->blsPubKeyOperator = dmn->pdmnState->pubKeyOperator;
- mn->keyIDVoting = dmn->pdmnState->keyIDVoting;
- mn->addr = dmn->pdmnState->addr;
- mn->nProtocolVersion = DMN_PROTO_VERSION;
-
- // If it appeared in the valid list, it is enabled no matter what
- mn->nActiveState = CMasternode::MASTERNODE_ENABLED;
- });
-
- added = oldMnCount != mapMasternodes.size();
- }
-
- if (added) {
- NotifyMasternodeUpdates(*g_connman, true, false);
- }
-}
-
-void CMasternodeMan::RemoveNonDeterministicMasternodes()
-{
- if (!deterministicMNManager->IsDeterministicMNsSporkActive())
- return;
-
- bool erased = false;
- {
- LOCK(cs);
- std::set mnSet;
- auto mnList = deterministicMNManager->GetListAtChainTip();
- mnList.ForEachMN(true, [&](const CDeterministicMNCPtr& dmn) {
- mnSet.insert(dmn->collateralOutpoint);
- });
- auto it = mapMasternodes.begin();
- while (it != mapMasternodes.end()) {
- if (!mnSet.count(it->second.outpoint)) {
- mapMasternodes.erase(it++);
- erased = true;
- } else {
- ++it;
- }
- }
- }
- if (erased) {
- NotifyMasternodeUpdates(*g_connman, false, true);
- }
-}
-
-void CMasternodeMan::Clear()
-{
- LOCK(cs);
- mapMasternodes.clear();
- mAskedUsForMasternodeList.clear();
- mWeAskedForMasternodeList.clear();
- mWeAskedForMasternodeListEntry.clear();
- mapSeenMasternodeBroadcast.clear();
- mapSeenMasternodePing.clear();
- nDsqCount = 0;
- nLastSentinelPingTime = 0;
-}
-
-int CMasternodeMan::CountMasternodes(int nProtocolVersion)
-{
- LOCK(cs);
-
- int nCount = 0;
- nProtocolVersion = nProtocolVersion == -1 ? mnpayments.GetMinMasternodePaymentsProto() : nProtocolVersion;
-
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
- auto mnList = deterministicMNManager->GetListAtChainTip();
- nCount = (int)mnList.GetAllMNsCount();
- } else {
- for (const auto& mnpair : mapMasternodes) {
- if(mnpair.second.nProtocolVersion < nProtocolVersion) continue;
- nCount++;
- }
- }
- return nCount;
-}
-
-int CMasternodeMan::CountEnabled(int nProtocolVersion)
-{
- LOCK(cs);
-
- int nCount = 0;
- nProtocolVersion = nProtocolVersion == -1 ? mnpayments.GetMinMasternodePaymentsProto() : nProtocolVersion;
-
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
- auto mnList = deterministicMNManager->GetListAtChainTip();
- nCount = (int)mnList.GetValidMNsCount();
- } else {
- for (const auto& mnpair : mapMasternodes) {
- if (mnpair.second.nProtocolVersion < nProtocolVersion || !mnpair.second.IsEnabled()) continue;
- nCount++;
- }
- }
-
- return nCount;
-}
-
-/* Only IPv4 masternodes are allowed in 12.1, saving this for later
-int CMasternodeMan::CountByIP(int nNetworkType)
-{
- LOCK(cs);
- int nNodeCount = 0;
-
- for (const auto& mnpair : mapMasternodes)
- if ((nNetworkType == NET_IPV4 && mnpair.second.addr.IsIPv4()) ||
- (nNetworkType == NET_TOR && mnpair.second.addr.IsTor()) ||
- (nNetworkType == NET_IPV6 && mnpair.second.addr.IsIPv6())) {
- nNodeCount++;
- }
-
- return nNodeCount;
-}
-*/
-
-void CMasternodeMan::DsegUpdate(CNode* pnode, CConnman& connman)
-{
- CNetMsgMaker msgMaker(pnode->GetSendVersion());
- LOCK(cs);
-
- if (deterministicMNManager->IsDeterministicMNsSporkActive())
- return;
-
- CService addrSquashed = Params().AllowMultiplePorts() ? (CService)pnode->addr : CService(pnode->addr, 0);
- if(Params().NetworkIDString() == CBaseChainParams::MAIN) {
- if(!(pnode->addr.IsRFC1918() || pnode->addr.IsLocal())) {
- auto it = mWeAskedForMasternodeList.find(addrSquashed);
- if(it != mWeAskedForMasternodeList.end() && GetTime() < (*it).second) {
- LogPrintf("CMasternodeMan::DsegUpdate -- we already asked %s for the list; skipping...\n", addrSquashed.ToString());
- return;
- }
- }
- }
-
- connman.PushMessage(pnode, msgMaker.Make(NetMsgType::DSEG, COutPoint()));
-
- int64_t askAgain = GetTime() + DSEG_UPDATE_SECONDS;
- mWeAskedForMasternodeList[addrSquashed] = askAgain;
-
- LogPrint("masternode", "CMasternodeMan::DsegUpdate -- asked %s for the list\n", pnode->addr.ToString());
-}
-
-CMasternode* CMasternodeMan::Find(const COutPoint &outpoint)
-{
- LOCK(cs);
-
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
- // This code keeps compatibility to old code depending on the non-deterministic MN lists
- // When deterministic MN lists get activated, we stop relying on the MNs we encountered due to MNBs and start
- // using the MNs found in the deterministic MN manager. To keep compatibility, we create CMasternode entries
- // for these and return them here. This is needed because we also need to track some data per MN that is not
- // on-chain, like vote counts
-
- auto mnList = deterministicMNManager->GetListAtChainTip();
- auto dmn = mnList.GetMNByCollateral(outpoint);
- if (!dmn || !mnList.IsMNValid(dmn)) {
- return nullptr;
- }
-
- auto it = mapMasternodes.find(outpoint);
- if (it != mapMasternodes.end()) {
- return &(it->second);
- } else {
- // MN is not in mapMasternodes but in the deterministic list. Create an entry in mapMasternodes for compatibility with legacy code
- CMasternode mn(outpoint.hash, dmn);
- it = mapMasternodes.emplace(outpoint, mn).first;
- return &(it->second);
- }
- } else {
- auto it = mapMasternodes.find(outpoint);
- return it == mapMasternodes.end() ? nullptr : &(it->second);
- }
-}
-
-bool CMasternodeMan::Get(const COutPoint& outpoint, CMasternode& masternodeRet)
-{
- // Theses mutexes are recursive so double locking by the same thread is safe.
- LOCK(cs);
- CMasternode* mn = Find(outpoint);
- if (!mn)
- return false;
- masternodeRet = *mn;
- return true;
-}
-
-bool CMasternodeMan::GetMasternodeInfo(const uint256& proTxHash, masternode_info_t& mnInfoRet)
-{
- auto dmn = deterministicMNManager->GetListAtChainTip().GetValidMN(proTxHash);
- if (!dmn)
- return false;
- return GetMasternodeInfo(dmn->collateralOutpoint, mnInfoRet);
-}
-
-bool CMasternodeMan::GetMasternodeInfo(const COutPoint& outpoint, masternode_info_t& mnInfoRet)
-{
- LOCK(cs);
- CMasternode* mn = Find(outpoint);
- if (!mn)
- return false;
- mnInfoRet = mn->GetInfo();
- return true;
-}
-
-bool CMasternodeMan::GetMasternodeInfo(const CKeyID& keyIDOperator, masternode_info_t& mnInfoRet) {
- LOCK(cs);
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
- return false;
- } else {
- for (const auto& mnpair : mapMasternodes) {
- if (mnpair.second.legacyKeyIDOperator == keyIDOperator) {
- mnInfoRet = mnpair.second.GetInfo();
- return true;
- }
- }
- return false;
- }
-}
-
-bool CMasternodeMan::GetMasternodeInfo(const CScript& payee, masternode_info_t& mnInfoRet)
-{
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
- // we can't reliably search by payee as there might be duplicates. Also, keyIDCollateralAddress is not
- // always the payout address as DIP3 allows using different keys for collateral and payouts
- // this method is only used from ComputeBlockVersion, which has a different logic for deterministic MNs
- // this method won't be reimplemented when removing the compatibility code
- return false;
- } else {
- CTxDestination dest;
- if (!ExtractDestination(payee, dest) || !boost::get(&dest))
- return false;
- CKeyID keyId = *boost::get(&dest);
- LOCK(cs);
- for (const auto& mnpair : mapMasternodes) {
- if (mnpair.second.keyIDCollateralAddress == keyId) {
- mnInfoRet = mnpair.second.GetInfo();
- return true;
- }
- }
- return false;
- }
-}
-
-bool CMasternodeMan::Has(const COutPoint& outpoint)
-{
- LOCK(cs);
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
- return deterministicMNManager->HasValidMNCollateralAtChainTip(outpoint);
- } else {
- return mapMasternodes.find(outpoint) != mapMasternodes.end();
- }
-}
-
-//
-// Deterministically select the oldest/best masternode to pay on the network
-//
-bool CMasternodeMan::GetNextMasternodeInQueueForPayment(bool fFilterSigTime, int& nCountRet, masternode_info_t& mnInfoRet)
-{
- return GetNextMasternodeInQueueForPayment(nCachedBlockHeight, fFilterSigTime, nCountRet, mnInfoRet);
-}
-
-bool CMasternodeMan::GetNextMasternodeInQueueForPayment(int nBlockHeight, bool fFilterSigTime, int& nCountRet, masternode_info_t& mnInfoRet)
-{
- if (deterministicMNManager->IsDeterministicMNsSporkActive(nBlockHeight)) {
- return false;
- }
-
- mnInfoRet = masternode_info_t();
- nCountRet = 0;
-
- if (!masternodeSync.IsWinnersListSynced()) {
- // without winner list we can't reliably find the next winner anyway
- return false;
- }
-
- // Need LOCK2 here to ensure consistent locking order because the GetBlockHash call below locks cs_main
- LOCK2(cs_main,cs);
-
- std::vector > vecMasternodeLastPaid;
-
- /*
- Make a vector with all of the last paid times
- */
-
- int nMnCount = CountMasternodes();
-
- for (const auto& mnpair : mapMasternodes) {
- if(!mnpair.second.IsValidForPayment()) continue;
-
- //check protocol version
- if(mnpair.second.nProtocolVersion < mnpayments.GetMinMasternodePaymentsProto()) continue;
-
- //it's in the list (up to 8 entries ahead of current block to allow propagation) -- so let's skip it
- if(mnpayments.IsScheduled(mnpair.second, nBlockHeight)) continue;
-
- //it's too new, wait for a cycle
- if(fFilterSigTime && mnpair.second.sigTime + (nMnCount*2.6*60) > GetAdjustedTime()) continue;
-
- //make sure it has at least as many confirmations as there are masternodes
- if(GetUTXOConfirmations(mnpair.first) < nMnCount) continue;
-
- vecMasternodeLastPaid.push_back(std::make_pair(mnpair.second.GetLastPaidBlock(), &mnpair.second));
- }
-
- nCountRet = (int)vecMasternodeLastPaid.size();
-
- //when the network is in the process of upgrading, don't penalize nodes that recently restarted
- if(fFilterSigTime && nCountRet < nMnCount/3)
- return GetNextMasternodeInQueueForPayment(nBlockHeight, false, nCountRet, mnInfoRet);
-
- // Sort them low to high
- sort(vecMasternodeLastPaid.begin(), vecMasternodeLastPaid.end(), CompareLastPaidBlock());
-
- uint256 blockHash;
- if(!GetBlockHash(blockHash, nBlockHeight - 101)) {
- LogPrintf("CMasternode::GetNextMasternodeInQueueForPayment -- ERROR: GetBlockHash() failed at nBlockHeight %d\n", nBlockHeight - 101);
- return false;
- }
- // Look at 1/10 of the oldest nodes (by last payment), calculate their scores and pay the best one
- // -- This doesn't look at who is being paid in the +8-10 blocks, allowing for double payments very rarely
- // -- 1/100 payments should be a double payment on mainnet - (1/(3000/10))*2
- // -- (chance per block * chances before IsScheduled will fire)
- int nTenthNetwork = nMnCount/10;
- int nCountTenth = 0;
- arith_uint256 nHighest = 0;
- const CMasternode *pBestMasternode = nullptr;
- for (const auto& s : vecMasternodeLastPaid) {
- arith_uint256 nScore = s.second->CalculateScore(blockHash);
- if(nScore > nHighest){
- nHighest = nScore;
- pBestMasternode = s.second;
- }
- nCountTenth++;
- if(nCountTenth >= nTenthNetwork) break;
- }
- if (pBestMasternode) {
- mnInfoRet = pBestMasternode->GetInfo();
- }
- return mnInfoRet.fInfoValid;
-}
-
-masternode_info_t CMasternodeMan::FindRandomNotInVec(const std::vector &vecToExclude, int nProtocolVersion)
-{
- LOCK(cs);
-
- nProtocolVersion = nProtocolVersion == -1 ? mnpayments.GetMinMasternodePaymentsProto() : nProtocolVersion;
-
- int nCountEnabled = CountEnabled(nProtocolVersion);
- int nCountNotExcluded = nCountEnabled - vecToExclude.size();
-
- LogPrintf("CMasternodeMan::FindRandomNotInVec -- %d enabled masternodes, %d masternodes to choose from\n", nCountEnabled, nCountNotExcluded);
- if(nCountNotExcluded < 1) return masternode_info_t();
-
- // fill a vector of pointers
- std::vector vpMasternodesShuffled;
- for (const auto& mnpair : mapMasternodes) {
- vpMasternodesShuffled.push_back(&mnpair.second);
- }
-
- FastRandomContext insecure_rand;
- // shuffle pointers
- std::random_shuffle(vpMasternodesShuffled.begin(), vpMasternodesShuffled.end(), insecure_rand);
- bool fExclude;
-
- // loop through
- for (const auto& pmn : vpMasternodesShuffled) {
- if(pmn->nProtocolVersion < nProtocolVersion || !pmn->IsEnabled()) continue;
- fExclude = false;
- for (const auto& outpointToExclude : vecToExclude) {
- if(pmn->outpoint == outpointToExclude) {
- fExclude = true;
- break;
- }
- }
- if(fExclude) continue;
- if (deterministicMNManager->IsDeterministicMNsSporkActive() && !deterministicMNManager->HasValidMNCollateralAtChainTip(pmn->outpoint))
- continue;
- // found the one not in vecToExclude
- LogPrint("masternode", "CMasternodeMan::FindRandomNotInVec -- found, masternode=%s\n", pmn->outpoint.ToStringShort());
- return pmn->GetInfo();
- }
-
- LogPrint("masternode", "CMasternodeMan::FindRandomNotInVec -- failed\n");
- return masternode_info_t();
-}
-
-std::map CMasternodeMan::GetFullMasternodeMap()
-{
- LOCK(cs);
-
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
- std::map result;
- auto mnList = deterministicMNManager->GetListAtChainTip();
- for (const auto &p : mapMasternodes) {
- auto dmn = mnList.GetMNByCollateral(p.first);
- if (dmn && mnList.IsMNValid(dmn)) {
- result.emplace(p.first, p.second);
- }
- }
- return result;
- } else {
- return mapMasternodes;
- }
-}
-
-bool CMasternodeMan::GetMasternodeScores(const uint256& nBlockHash, CMasternodeMan::score_pair_vec_t& vecMasternodeScoresRet, int nMinProtocol)
-{
- AssertLockHeld(cs);
-
- vecMasternodeScoresRet.clear();
-
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
- auto mnList = deterministicMNManager->GetListAtChainTip();
- auto scores = mnList.CalculateScores(nBlockHash);
- for (const auto& p : scores) {
- auto* mn = Find(p.second->collateralOutpoint);
- vecMasternodeScoresRet.emplace_back(p.first, mn);
- }
- } else {
- if (!masternodeSync.IsMasternodeListSynced())
- return false;
-
- if (mapMasternodes.empty())
- return false;
-
- // calculate scores
- for (const auto& mnpair : mapMasternodes) {
- if (mnpair.second.nProtocolVersion >= nMinProtocol) {
- vecMasternodeScoresRet.push_back(std::make_pair(mnpair.second.CalculateScore(nBlockHash), &mnpair.second));
- }
- }
- }
- sort(vecMasternodeScoresRet.rbegin(), vecMasternodeScoresRet.rend(), CompareScoreMN());
- return !vecMasternodeScoresRet.empty();
-}
-
-bool CMasternodeMan::GetMasternodeRank(const COutPoint& outpoint, int& nRankRet, int nBlockHeight, int nMinProtocol)
-{
- uint256 tmp;
- return GetMasternodeRank(outpoint, nRankRet, tmp, nBlockHeight, nMinProtocol);
-}
-
-bool CMasternodeMan::GetMasternodeRank(const COutPoint& outpoint, int& nRankRet, uint256& blockHashRet, int nBlockHeight, int nMinProtocol)
-{
- nRankRet = -1;
-
- if (!masternodeSync.IsMasternodeListSynced())
- return false;
-
- // make sure we know about this block
- blockHashRet = uint256();
- if (!GetBlockHash(blockHashRet, nBlockHeight)) {
- LogPrintf("CMasternodeMan::%s -- ERROR: GetBlockHash() failed at nBlockHeight %d\n", __func__, nBlockHeight);
- return false;
- }
-
- LOCK(cs);
-
- score_pair_vec_t vecMasternodeScores;
- if (!GetMasternodeScores(blockHashRet, vecMasternodeScores, nMinProtocol))
- return false;
-
- int nRank = 0;
- for (const auto& scorePair : vecMasternodeScores) {
- nRank++;
- if(scorePair.second->outpoint == outpoint) {
- nRankRet = nRank;
- return true;
- }
- }
-
- return false;
-}
-
-bool CMasternodeMan::GetMasternodeRanks(CMasternodeMan::rank_pair_vec_t& vecMasternodeRanksRet, int nBlockHeight, int nMinProtocol)
-{
- vecMasternodeRanksRet.clear();
-
- if (!masternodeSync.IsMasternodeListSynced())
- return false;
-
- // make sure we know about this block
- uint256 nBlockHash = uint256();
- if (!GetBlockHash(nBlockHash, nBlockHeight)) {
- LogPrintf("CMasternodeMan::%s -- ERROR: GetBlockHash() failed at nBlockHeight %d\n", __func__, nBlockHeight);
- return false;
- }
-
- LOCK(cs);
-
- score_pair_vec_t vecMasternodeScores;
- if (!GetMasternodeScores(nBlockHash, vecMasternodeScores, nMinProtocol))
- return false;
-
- int nRank = 0;
- for (const auto& scorePair : vecMasternodeScores) {
- nRank++;
- vecMasternodeRanksRet.push_back(std::make_pair(nRank, *scorePair.second));
- }
-
- return true;
-}
-
-void CMasternodeMan::ProcessMasternodeConnections(CConnman& connman)
-{
- std::vector vecMnInfo; // will be empty when no wallet
-#ifdef ENABLE_WALLET
- privateSendClient.GetMixingMasternodesInfo(vecMnInfo);
-#endif // ENABLE_WALLET
-
- connman.ForEachNode(CConnman::AllNodes, [&vecMnInfo](CNode* pnode) {
- if (pnode->fMasternode) {
-#ifdef ENABLE_WALLET
- bool fFound = false;
- for (const auto& mnInfo : vecMnInfo) {
- if (pnode->addr == mnInfo.addr) {
- fFound = true;
- break;
- }
- }
- if (fFound) return; // do NOT disconnect mixing masternodes
-#endif // ENABLE_WALLET
- LogPrintf("Closing Masternode connection: peer=%d, addr=%s\n", pnode->id, pnode->addr.ToString());
- pnode->fDisconnect = true;
- }
- });
-}
-
-std::pair > CMasternodeMan::PopScheduledMnbRequestConnection()
-{
- LOCK(cs);
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
- return std::make_pair(CService(), std::set());
- }
- if(listScheduledMnbRequestConnections.empty()) {
- return std::make_pair(CService(), std::set());
- }
-
- std::set setResult;
-
- listScheduledMnbRequestConnections.sort();
- std::pair pairFront = listScheduledMnbRequestConnections.front();
-
- // squash hashes from requests with the same CService as the first one into setResult
- std::list< std::pair >::iterator it = listScheduledMnbRequestConnections.begin();
- while(it != listScheduledMnbRequestConnections.end()) {
- if(pairFront.first == it->first) {
- setResult.insert(it->second);
- it = listScheduledMnbRequestConnections.erase(it);
- } else {
- // since list is sorted now, we can be sure that there is no more hashes left
- // to ask for from this addr
- break;
- }
- }
- return std::make_pair(pairFront.first, setResult);
-}
-
-void CMasternodeMan::ProcessPendingMnbRequests(CConnman& connman)
-{
- if (deterministicMNManager->IsDeterministicMNsSporkActive())
- return;
-
- std::pair > p = PopScheduledMnbRequestConnection();
- if (!(p.first == CService() || p.second.empty())) {
- if (connman.IsMasternodeOrDisconnectRequested(p.first)) return;
- mapPendingMNB.insert(std::make_pair(p.first, std::make_pair(GetTime(), p.second)));
- connman.AddPendingMasternode(p.first);
- }
-
- std::map > >::iterator itPendingMNB = mapPendingMNB.begin();
- while (itPendingMNB != mapPendingMNB.end()) {
- bool fDone = connman.ForNode(itPendingMNB->first, [&](CNode* pnode) {
- // compile request vector
- std::vector vToFetch;
- for (auto& nHash : itPendingMNB->second.second) {
- if(nHash != uint256()) {
- vToFetch.push_back(CInv(MSG_MASTERNODE_ANNOUNCE, nHash));
- LogPrint("masternode", "-- asking for mnb %s from addr=%s\n", nHash.ToString(), pnode->addr.ToString());
- }
- }
-
- // ask for data
- CNetMsgMaker msgMaker(pnode->GetSendVersion());
- connman.PushMessage(pnode, msgMaker.Make(NetMsgType::GETDATA, vToFetch));
- return true;
- });
-
- int64_t nTimeAdded = itPendingMNB->second.first;
- if (fDone || (GetTime() - nTimeAdded > 15)) {
- if (!fDone) {
- LogPrint("masternode", "CMasternodeMan::%s -- failed to connect to %s\n", __func__, itPendingMNB->first.ToString());
- }
- mapPendingMNB.erase(itPendingMNB++);
- } else {
- ++itPendingMNB;
- }
- }
-}
-
-void CMasternodeMan::ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, CConnman& connman)
-{
- if (deterministicMNManager->IsDeterministicMNsSporkActive())
- return;
-
- if(fLiteMode) return; // disable all Dash specific functionality
-
- if (strCommand == NetMsgType::MNANNOUNCE) { //Masternode Broadcast
-
- CMasternodeBroadcast mnb;
- vRecv >> mnb;
-
- {
- LOCK(cs_main);
- connman.RemoveAskFor(mnb.GetHash());
- }
-
- if(!masternodeSync.IsBlockchainSynced()) return;
-
- LogPrint("masternode", "MNANNOUNCE -- Masternode announce, masternode=%s\n", mnb.outpoint.ToStringShort());
-
- int nDos = 0;
-
- if (CheckMnbAndUpdateMasternodeList(pfrom, mnb, nDos, connman)) {
- // use announced Masternode as a peer
- connman.AddNewAddress(CAddress(mnb.addr, NODE_NETWORK), pfrom->addr, 2*60*60);
- } else if(nDos > 0) {
- LOCK(cs_main);
- Misbehaving(pfrom->GetId(), nDos);
- }
-
- if(fMasternodesAdded) {
- NotifyMasternodeUpdates(connman);
- }
- } else if (strCommand == NetMsgType::MNPING) { //Masternode Ping
-
- CMasternodePing mnp;
- vRecv >> mnp;
-
- uint256 nHash = mnp.GetHash();
-
- {
- LOCK(cs_main);
- connman.RemoveAskFor(nHash);
- }
-
- if(!masternodeSync.IsBlockchainSynced()) return;
-
- LogPrint("masternode", "MNPING -- Masternode ping, masternode=%s\n", mnp.masternodeOutpoint.ToStringShort());
-
- // Need LOCK2 here to ensure consistent locking order because the CheckAndUpdate call below locks cs_main
- LOCK2(cs_main, cs);
-
- if(mapSeenMasternodePing.count(nHash)) return; //seen
- mapSeenMasternodePing.insert(std::make_pair(nHash, mnp));
-
- LogPrint("masternode", "MNPING -- Masternode ping, masternode=%s new\n", mnp.masternodeOutpoint.ToStringShort());
-
- // see if we have this Masternode
- CMasternode* pmn = Find(mnp.masternodeOutpoint);
-
- if(pmn && mnp.fSentinelIsCurrent)
- UpdateLastSentinelPingTime();
-
- // too late, new MNANNOUNCE is required
- if(pmn && pmn->IsNewStartRequired()) return;
-
- int nDos = 0;
- if(mnp.CheckAndUpdate(pmn, false, nDos, connman)) return;
-
- if(nDos > 0) {
- // if anything significant failed, mark that node
- Misbehaving(pfrom->GetId(), nDos);
- } else if(pmn != nullptr) {
- // nothing significant failed, mn is a known one too
- return;
- }
-
- // something significant is broken or mn is unknown,
- // we might have to ask for a masternode entry once
- AskForMN(pfrom, mnp.masternodeOutpoint, connman);
-
- } else if (strCommand == NetMsgType::DSEG) { //Get Masternode list or specific entry
- // Ignore such requests until we are fully synced.
- // We could start processing this after masternode list is synced
- // but this is a heavy one so it's better to finish sync first.
- if (!masternodeSync.IsSynced()) return;
-
- COutPoint masternodeOutpoint;
- vRecv >> masternodeOutpoint;
-
- LogPrint("masternode", "DSEG -- Masternode list, masternode=%s\n", masternodeOutpoint.ToStringShort());
-
- if(masternodeOutpoint.IsNull()) {
- SyncAll(pfrom, connman);
- } else {
- SyncSingle(pfrom, masternodeOutpoint, connman);
- }
-
- } else if (strCommand == NetMsgType::MNVERIFY) { // Masternode Verify
-
- // Need LOCK2 here to ensure consistent locking order because all functions below call GetBlockHash which locks cs_main
- LOCK2(cs_main, cs);
-
- CMasternodeVerification mnv;
- vRecv >> mnv;
-
- {
- LOCK(cs_main);
- connman.RemoveAskFor(mnv.GetHash());
- }
-
- if(!masternodeSync.IsMasternodeListSynced()) return;
-
- if(mnv.vchSig1.empty()) {
- // CASE 1: someone asked me to verify myself /IP we are using/
- SendVerifyReply(pfrom, mnv, connman);
- } else if (mnv.vchSig2.empty()) {
- // CASE 2: we _probably_ got verification we requested from some masternode
- ProcessVerifyReply(pfrom, mnv);
- } else {
- // CASE 3: we _probably_ got verification broadcast signed by some masternode which verified another one
- ProcessVerifyBroadcast(pfrom, mnv);
- }
- }
-}
-
-void CMasternodeMan::SyncSingle(CNode* pnode, const COutPoint& outpoint, CConnman& connman)
-{
- // do not provide any data until our node is synced
- if (!masternodeSync.IsSynced()) return;
-
- LOCK(cs);
-
- auto it = mapMasternodes.find(outpoint);
-
- if(it != mapMasternodes.end()) {
- if (it->second.addr.IsRFC1918() || it->second.addr.IsLocal()) return; // do not send local network masternode
- // NOTE: send masternode regardless of its current state, the other node will need it to verify old votes.
- LogPrint("masternode", "CMasternodeMan::%s -- Sending Masternode entry: masternode=%s addr=%s\n", __func__, outpoint.ToStringShort(), it->second.addr.ToString());
- PushDsegInvs(pnode, it->second);
- LogPrintf("CMasternodeMan::%s -- Sent 1 Masternode inv to peer=%d\n", __func__, pnode->id);
- }
-}
-
-void CMasternodeMan::SyncAll(CNode* pnode, CConnman& connman)
-{
- // do not provide any data until our node is synced
- if (!masternodeSync.IsSynced()) return;
-
- // local network
- bool isLocal = (pnode->addr.IsRFC1918() || pnode->addr.IsLocal());
-
- CService addrSquashed = Params().AllowMultiplePorts() ? (CService)pnode->addr : CService(pnode->addr, 0);
- // should only ask for this once
- if(!isLocal && Params().NetworkIDString() == CBaseChainParams::MAIN) {
- LOCK2(cs_main, cs);
- auto it = mAskedUsForMasternodeList.find(addrSquashed);
- if (it != mAskedUsForMasternodeList.end() && it->second > GetTime()) {
- Misbehaving(pnode->GetId(), 34);
- LogPrintf("CMasternodeMan::%s -- peer already asked me for the list, peer=%d\n", __func__, pnode->id);
- return;
- }
- int64_t askAgain = GetTime() + DSEG_UPDATE_SECONDS;
- mAskedUsForMasternodeList[addrSquashed] = askAgain;
- }
-
- int nInvCount = 0;
-
- LOCK(cs);
-
- for (const auto& mnpair : mapMasternodes) {
- if (Params().RequireRoutableExternalIP() &&
- (mnpair.second.addr.IsRFC1918() || mnpair.second.addr.IsLocal()))
- continue; // do not send local network masternode
- // NOTE: send masternode regardless of its current state, the other node will need it to verify old votes.
- LogPrint("masternode", "CMasternodeMan::%s -- Sending Masternode entry: masternode=%s addr=%s\n", __func__, mnpair.first.ToStringShort(), mnpair.second.addr.ToString());
- PushDsegInvs(pnode, mnpair.second);
- nInvCount++;
- }
-
- connman.PushMessage(pnode, CNetMsgMaker(pnode->GetSendVersion()).Make(NetMsgType::SYNCSTATUSCOUNT, MASTERNODE_SYNC_LIST, nInvCount));
- LogPrintf("CMasternodeMan::%s -- Sent %d Masternode invs to peer=%d\n", __func__, nInvCount, pnode->id);
-}
-
-void CMasternodeMan::PushDsegInvs(CNode* pnode, const CMasternode& mn)
-{
- AssertLockHeld(cs);
-
- CMasternodeBroadcast mnb(mn);
- CMasternodePing mnp = mnb.lastPing;
- uint256 hashMNB = mnb.GetHash();
- uint256 hashMNP = mnp.GetHash();
- pnode->PushInventory(CInv(MSG_MASTERNODE_ANNOUNCE, hashMNB));
- pnode->PushInventory(CInv(MSG_MASTERNODE_PING, hashMNP));
- mapSeenMasternodeBroadcast.insert(std::make_pair(hashMNB, std::make_pair(GetTime(), mnb)));
- mapSeenMasternodePing.insert(std::make_pair(hashMNP, mnp));
-}
-
-// Verification of masternodes via unique direct requests.
-
-void CMasternodeMan::DoFullVerificationStep(CConnman& connman)
-{
- if (deterministicMNManager->IsDeterministicMNsSporkActive())
- return;
-
- if(activeMasternodeInfo.outpoint.IsNull()) return;
- if(!masternodeSync.IsSynced()) return;
-
- rank_pair_vec_t vecMasternodeRanks;
- GetMasternodeRanks(vecMasternodeRanks, nCachedBlockHeight - 1, MIN_POSE_PROTO_VERSION);
-
- std::vector vAddr;
-
- {
- LOCK(cs);
-
- int nMyRank = -1;
- int nRanksTotal = (int)vecMasternodeRanks.size();
-
- // send verify requests only if we are in top MAX_POSE_RANK
- for (auto& rankPair : vecMasternodeRanks) {
- if(rankPair.first > MAX_POSE_RANK) {
- LogPrint("masternode", "CMasternodeMan::DoFullVerificationStep -- Must be in top %d to send verify request\n",
- (int)MAX_POSE_RANK);
- return;
- }
- if(rankPair.second.outpoint == activeMasternodeInfo.outpoint) {
- nMyRank = rankPair.first;
- LogPrint("masternode", "CMasternodeMan::DoFullVerificationStep -- Found self at rank %d/%d, verifying up to %d masternodes\n",
- nMyRank, nRanksTotal, (int)MAX_POSE_CONNECTIONS);
- break;
- }
- }
-
- // edge case: list is too short and this masternode is not enabled
- if(nMyRank == -1) return;
-
- // send verify requests to up to MAX_POSE_CONNECTIONS masternodes
- // starting from MAX_POSE_RANK + nMyRank and using MAX_POSE_CONNECTIONS as a step
- int nOffset = MAX_POSE_RANK + nMyRank - 1;
- if(nOffset >= (int)vecMasternodeRanks.size()) return;
-
- auto it = vecMasternodeRanks.begin() + nOffset;
- while(it != vecMasternodeRanks.end()) {
- if(it->second.IsPoSeVerified() || it->second.IsPoSeBanned()) {
- LogPrint("masternode", "CMasternodeMan::DoFullVerificationStep -- Already %s%s%s masternode %s address %s, skipping...\n",
- it->second.IsPoSeVerified() ? "verified" : "",
- it->second.IsPoSeVerified() && it->second.IsPoSeBanned() ? " and " : "",
- it->second.IsPoSeBanned() ? "banned" : "",
- it->second.outpoint.ToStringShort(), it->second.addr.ToString());
- nOffset += MAX_POSE_CONNECTIONS;
- if(nOffset >= (int)vecMasternodeRanks.size()) break;
- it += MAX_POSE_CONNECTIONS;
- continue;
- }
- LogPrint("masternode", "CMasternodeMan::DoFullVerificationStep -- Verifying masternode %s rank %d/%d address %s\n",
- it->second.outpoint.ToStringShort(), it->first, nRanksTotal, it->second.addr.ToString());
- CAddress addr = CAddress(it->second.addr, NODE_NETWORK);
- if(CheckVerifyRequestAddr(addr, connman)) {
- vAddr.push_back(addr);
- if((int)vAddr.size() >= MAX_POSE_CONNECTIONS) break;
- }
- nOffset += MAX_POSE_CONNECTIONS;
- if(nOffset >= (int)vecMasternodeRanks.size()) break;
- it += MAX_POSE_CONNECTIONS;
- }
- } // cs
-
- for (const auto& addr : vAddr) {
- PrepareVerifyRequest(addr, connman);
- }
-
- LogPrint("masternode", "CMasternodeMan::DoFullVerificationStep -- Prepared verification requests for %d masternodes\n", vAddr.size());
-}
-
-// This function tries to find masternodes with the same addr,
-// find a verified one and ban all the other. If there are many nodes
-// with the same addr but none of them is verified yet, then none of them are banned.
-// It could take many times to run this before most of the duplicate nodes are banned.
-
-void CMasternodeMan::CheckSameAddr()
-{
- if (deterministicMNManager->IsDeterministicMNsSporkActive())
- return;
-
- if(!masternodeSync.IsSynced() || mapMasternodes.empty()) return;
-
- std::vector vBan;
- std::vector vSortedByAddr;
-
- {
- LOCK(cs);
-
- CMasternode* pprevMasternode = nullptr;
- CMasternode* pverifiedMasternode = nullptr;
-
- for (auto& mnpair : mapMasternodes) {
- vSortedByAddr.push_back(&mnpair.second);
- }
-
- sort(vSortedByAddr.begin(), vSortedByAddr.end(), CompareByAddr());
-
- for (const auto& pmn : vSortedByAddr) {
- // check only (pre)enabled masternodes
- if(!pmn->IsEnabled() && !pmn->IsPreEnabled()) continue;
- // initial step
- if(!pprevMasternode) {
- pprevMasternode = pmn;
- pverifiedMasternode = pmn->IsPoSeVerified() ? pmn : nullptr;
- continue;
- }
- // second+ step
- if(pmn->addr == pprevMasternode->addr) {
- if(pverifiedMasternode) {
- // another masternode with the same ip is verified, ban this one
- vBan.push_back(pmn);
- } else if(pmn->IsPoSeVerified()) {
- // this masternode with the same ip is verified, ban previous one
- vBan.push_back(pprevMasternode);
- // and keep a reference to be able to ban following masternodes with the same ip
- pverifiedMasternode = pmn;
- }
- } else {
- pverifiedMasternode = pmn->IsPoSeVerified() ? pmn : nullptr;
- }
- pprevMasternode = pmn;
- }
- }
-
- // ban duplicates
- for (auto& pmn : vBan) {
- LogPrintf("CMasternodeMan::CheckSameAddr -- increasing PoSe ban score for masternode %s\n", pmn->outpoint.ToStringShort());
- pmn->IncreasePoSeBanScore();
- }
-}
-
-bool CMasternodeMan::CheckVerifyRequestAddr(const CAddress& addr, CConnman& connman)
-{
- if (deterministicMNManager->IsDeterministicMNsSporkActive())
- return false;
-
- if(netfulfilledman.HasFulfilledRequest(addr, strprintf("%s", NetMsgType::MNVERIFY)+"-request")) {
- // we already asked for verification, not a good idea to do this too often, skip it
- LogPrint("masternode", "CMasternodeMan::%s -- too many requests, skipping... addr=%s\n", __func__, addr.ToString());
- return false;
- }
-
- return !connman.IsMasternodeOrDisconnectRequested(addr);
-}
-
-void CMasternodeMan::PrepareVerifyRequest(const CAddress& addr, CConnman& connman)
-{
- connman.AddPendingMasternode(addr);
- // use random nonce, store it and require node to reply with correct one later
- CMasternodeVerification mnv(addr, GetRandInt(999999), nCachedBlockHeight - 1);
- LOCK(cs_mapPendingMNV);
- mapPendingMNV.insert(std::make_pair(addr, std::make_pair(GetTime(), mnv)));
- LogPrintf("CMasternodeMan::%s -- verifying node using nonce %d addr=%s\n", __func__, mnv.nonce, addr.ToString());
-}
-
-void CMasternodeMan::ProcessPendingMnvRequests(CConnman& connman)
-{
- LOCK(cs_mapPendingMNV);
-
- if (deterministicMNManager->IsDeterministicMNsSporkActive())
- return;
-
- std::map >::iterator itPendingMNV = mapPendingMNV.begin();
-
- while (itPendingMNV != mapPendingMNV.end()) {
- bool fDone = connman.ForNode(itPendingMNV->first, [&](CNode* pnode) {
- netfulfilledman.AddFulfilledRequest(pnode->addr, strprintf("%s", NetMsgType::MNVERIFY)+"-request");
- // use random nonce, store it and require node to reply with correct one later
- mWeAskedForVerification[pnode->addr] = itPendingMNV->second.second;
- LogPrint("masternode", "-- verifying node using nonce %d addr=%s\n", itPendingMNV->second.second.nonce, pnode->addr.ToString());
- CNetMsgMaker msgMaker(pnode->GetSendVersion()); // TODO this gives a warning about version not being set (we should wait for VERSION exchange)
- connman.PushMessage(pnode, msgMaker.Make(NetMsgType::MNVERIFY, itPendingMNV->second.second));
- return true;
- });
-
- int64_t nTimeAdded = itPendingMNV->second.first;
- if (fDone || (GetTime() - nTimeAdded > 15)) {
- if (!fDone) {
- LogPrint("masternode", "CMasternodeMan::%s -- failed to connect to %s\n", __func__, itPendingMNV->first.ToString());
- }
- mapPendingMNV.erase(itPendingMNV++);
- } else {
- ++itPendingMNV;
- }
- }
-}
-
-void CMasternodeMan::SendVerifyReply(CNode* pnode, CMasternodeVerification& mnv, CConnman& connman)
-{
- AssertLockHeld(cs_main);
-
- if (deterministicMNManager->IsDeterministicMNsSporkActive())
- return;
-
- // only masternodes can sign this, why would someone ask regular node?
- if(!fMasternodeMode) {
- // do not ban, malicious node might be using my IP
- // and trying to confuse the node which tries to verify it
- return;
- }
-
- if(netfulfilledman.HasFulfilledRequest(pnode->addr, strprintf("%s", NetMsgType::MNVERIFY)+"-reply")) {
- // peer should not ask us that often
- LogPrintf("MasternodeMan::SendVerifyReply -- ERROR: peer already asked me recently, peer=%d\n", pnode->id);
- Misbehaving(pnode->id, 20);
- return;
- }
-
- uint256 blockHash;
- if(!GetBlockHash(blockHash, mnv.nBlockHeight)) {
- LogPrintf("MasternodeMan::SendVerifyReply -- can't get block hash for unknown block height %d, peer=%d\n", mnv.nBlockHeight, pnode->id);
- return;
- }
-
- std::string strError;
-
- if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
- uint256 hash = mnv.GetSignatureHash1(blockHash);
-
- if(!CHashSigner::SignHash(hash, activeMasternodeInfo.legacyKeyOperator, mnv.vchSig1)) {
- LogPrintf("CMasternodeMan::SendVerifyReply -- SignHash() failed\n");
- return;
- }
-
- if (!CHashSigner::VerifyHash(hash, activeMasternodeInfo.legacyKeyIDOperator, mnv.vchSig1, strError)) {
- LogPrintf("CMasternodeMan::SendVerifyReply -- VerifyHash() failed, error: %s\n", strError);
- return;
- }
- } else {
- std::string strMessage = strprintf("%s%d%s", activeMasternodeInfo.service.ToString(false), mnv.nonce, blockHash.ToString());
-
- if(!CMessageSigner::SignMessage(strMessage, mnv.vchSig1, activeMasternodeInfo.legacyKeyOperator)) {
- LogPrintf("MasternodeMan::SendVerifyReply -- SignMessage() failed\n");
- return;
- }
-
- if(!CMessageSigner::VerifyMessage(activeMasternodeInfo.legacyKeyIDOperator, mnv.vchSig1, strMessage, strError)) {
- LogPrintf("MasternodeMan::SendVerifyReply -- VerifyMessage() failed, error: %s\n", strError);
- return;
- }
- }
-
- CNetMsgMaker msgMaker(pnode->GetSendVersion());
- connman.PushMessage(pnode, msgMaker.Make(NetMsgType::MNVERIFY, mnv));
- netfulfilledman.AddFulfilledRequest(pnode->addr, strprintf("%s", NetMsgType::MNVERIFY)+"-reply");
-}
-
-void CMasternodeMan::ProcessVerifyReply(CNode* pnode, CMasternodeVerification& mnv)
-{
- AssertLockHeld(cs_main);
-
- if (deterministicMNManager->IsDeterministicMNsSporkActive())
- return;
-
- std::string strError;
-
- // did we even ask for it? if that's the case we should have matching fulfilled request
- if(!netfulfilledman.HasFulfilledRequest(pnode->addr, strprintf("%s", NetMsgType::MNVERIFY)+"-request")) {
- LogPrintf("CMasternodeMan::ProcessVerifyReply -- ERROR: we didn't ask for verification of %s, peer=%d\n", pnode->addr.ToString(), pnode->id);
- Misbehaving(pnode->id, 20);
- return;
- }
-
- // Received nonce for a known address must match the one we sent
- if(mWeAskedForVerification[pnode->addr].nonce != mnv.nonce) {
- LogPrintf("CMasternodeMan::ProcessVerifyReply -- ERROR: wrong nounce: requested=%d, received=%d, peer=%d\n",
- mWeAskedForVerification[pnode->addr].nonce, mnv.nonce, pnode->id);
- Misbehaving(pnode->id, 20);
- return;
- }
-
- // Received nBlockHeight for a known address must match the one we sent
- if(mWeAskedForVerification[pnode->addr].nBlockHeight != mnv.nBlockHeight) {
- LogPrintf("CMasternodeMan::ProcessVerifyReply -- ERROR: wrong nBlockHeight: requested=%d, received=%d, peer=%d\n",
- mWeAskedForVerification[pnode->addr].nBlockHeight, mnv.nBlockHeight, pnode->id);
- Misbehaving(pnode->id, 20);
- return;
- }
-
- uint256 blockHash;
- if(!GetBlockHash(blockHash, mnv.nBlockHeight)) {
- // this shouldn't happen...
- LogPrintf("MasternodeMan::ProcessVerifyReply -- can't get block hash for unknown block height %d, peer=%d\n", mnv.nBlockHeight, pnode->id);
- return;
- }
-
- // we already verified this address, why node is spamming?
- if(netfulfilledman.HasFulfilledRequest(pnode->addr, strprintf("%s", NetMsgType::MNVERIFY)+"-done")) {
- LogPrintf("CMasternodeMan::ProcessVerifyReply -- ERROR: already verified %s recently\n", pnode->addr.ToString());
- Misbehaving(pnode->id, 20);
- return;
- }
-
- {
- LOCK(cs);
-
- CMasternode* prealMasternode = nullptr;
- std::vector vpMasternodesToBan;
-
- uint256 hash1 = mnv.GetSignatureHash1(blockHash);
- std::string strMessage1 = strprintf("%s%d%s", pnode->addr.ToString(false), mnv.nonce, blockHash.ToString());
-
- for (auto& mnpair : mapMasternodes) {
- if(CAddress(mnpair.second.addr, NODE_NETWORK) == pnode->addr) {
- bool fFound = false;
- if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
- fFound = CHashSigner::VerifyHash(hash1, mnpair.second.legacyKeyIDOperator, mnv.vchSig1, strError);
- // we don't care about mnv with signature in old format
- } else {
- fFound = CMessageSigner::VerifyMessage(mnpair.second.legacyKeyIDOperator, mnv.vchSig1, strMessage1, strError);
- }
- if (fFound) {
- // found it!
- prealMasternode = &mnpair.second;
- if(!mnpair.second.IsPoSeVerified()) {
- mnpair.second.DecreasePoSeBanScore();
- }
- netfulfilledman.AddFulfilledRequest(pnode->addr, strprintf("%s", NetMsgType::MNVERIFY)+"-done");
-
- // we can only broadcast it if we are an activated masternode
- if(activeMasternodeInfo.outpoint.IsNull()) continue;
- // update ...
- mnv.addr = mnpair.second.addr;
- mnv.masternodeOutpoint1 = mnpair.second.outpoint;
- mnv.masternodeOutpoint2 = activeMasternodeInfo.outpoint;
- // ... and sign it
- std::string strError;
-
- if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
- uint256 hash2 = mnv.GetSignatureHash2(blockHash);
-
- if(!CHashSigner::SignHash(hash2, activeMasternodeInfo.legacyKeyOperator, mnv.vchSig2)) {
- LogPrintf("MasternodeMan::ProcessVerifyReply -- SignHash() failed\n");
- return;
- }
-
- if(!CHashSigner::VerifyHash(hash2, activeMasternodeInfo.legacyKeyIDOperator, mnv.vchSig2, strError)) {
- LogPrintf("MasternodeMan::ProcessVerifyReply -- VerifyHash() failed, error: %s\n", strError);
- return;
- }
- } else {
- std::string strMessage2 = strprintf("%s%d%s%s%s", mnv.addr.ToString(false), mnv.nonce, blockHash.ToString(),
- mnv.masternodeOutpoint1.ToStringShort(), mnv.masternodeOutpoint2.ToStringShort());
-
- if(!CMessageSigner::SignMessage(strMessage2, mnv.vchSig2, activeMasternodeInfo.legacyKeyOperator)) {
- LogPrintf("MasternodeMan::ProcessVerifyReply -- SignMessage() failed\n");
- return;
- }
-
- if(!CMessageSigner::VerifyMessage(activeMasternodeInfo.legacyKeyIDOperator, mnv.vchSig2, strMessage2, strError)) {
- LogPrintf("MasternodeMan::ProcessVerifyReply -- VerifyMessage() failed, error: %s\n", strError);
- return;
- }
- }
-
- mWeAskedForVerification[pnode->addr] = mnv;
- mapSeenMasternodeVerification.insert(std::make_pair(mnv.GetHash(), mnv));
- mnv.Relay();
-
- } else {
- vpMasternodesToBan.push_back(&mnpair.second);
- }
- }
- }
- // no real masternode found?...
- if(!prealMasternode) {
- // this should never be the case normally,
- // only if someone is trying to game the system in some way or smth like that
- LogPrintf("CMasternodeMan::ProcessVerifyReply -- ERROR: no real masternode found for addr %s\n", pnode->addr.ToString());
- Misbehaving(pnode->id, 20);
- return;
- }
- LogPrintf("CMasternodeMan::ProcessVerifyReply -- verified real masternode %s for addr %s\n",
- prealMasternode->outpoint.ToStringShort(), pnode->addr.ToString());
- // increase ban score for everyone else
- for (const auto& pmn : vpMasternodesToBan) {
- pmn->IncreasePoSeBanScore();
- LogPrint("masternode", "CMasternodeMan::ProcessVerifyReply -- increased PoSe ban score for %s addr %s, new score %d\n",
- prealMasternode->outpoint.ToStringShort(), pnode->addr.ToString(), pmn->nPoSeBanScore);
- }
- if(!vpMasternodesToBan.empty())
- LogPrintf("CMasternodeMan::ProcessVerifyReply -- PoSe score increased for %d fake masternodes, addr %s\n",
- (int)vpMasternodesToBan.size(), pnode->addr.ToString());
- }
-}
-
-void CMasternodeMan::ProcessVerifyBroadcast(CNode* pnode, const CMasternodeVerification& mnv)
-{
- AssertLockHeld(cs_main);
-
- if (deterministicMNManager->IsDeterministicMNsSporkActive())
- return;
-
- std::string strError;
-
- if(mapSeenMasternodeVerification.find(mnv.GetHash()) != mapSeenMasternodeVerification.end()) {
- // we already have one
- return;
- }
- mapSeenMasternodeVerification[mnv.GetHash()] = mnv;
-
- // we don't care about history
- if(mnv.nBlockHeight < nCachedBlockHeight - MAX_POSE_BLOCKS) {
- LogPrint("masternode", "CMasternodeMan::ProcessVerifyBroadcast -- Outdated: current block %d, verification block %d, peer=%d\n",
- nCachedBlockHeight, mnv.nBlockHeight, pnode->id);
- return;
- }
-
- if(mnv.masternodeOutpoint1 == mnv.masternodeOutpoint2) {
- LogPrint("masternode", "CMasternodeMan::ProcessVerifyBroadcast -- ERROR: same outpoints %s, peer=%d\n",
- mnv.masternodeOutpoint1.ToStringShort(), pnode->id);
- // that was NOT a good idea to cheat and verify itself,
- // ban the node we received such message from
- Misbehaving(pnode->id, 100);
- return;
- }
-
- uint256 blockHash;
- if(!GetBlockHash(blockHash, mnv.nBlockHeight)) {
- // this shouldn't happen...
- LogPrintf("CMasternodeMan::ProcessVerifyBroadcast -- Can't get block hash for unknown block height %d, peer=%d\n", mnv.nBlockHeight, pnode->id);
- return;
- }
-
- int nRank;
-
- if (!GetMasternodeRank(mnv.masternodeOutpoint2, nRank, mnv.nBlockHeight, MIN_POSE_PROTO_VERSION)) {
- LogPrint("masternode", "CMasternodeMan::ProcessVerifyBroadcast -- Can't calculate rank for masternode %s\n",
- mnv.masternodeOutpoint2.ToStringShort());
- return;
- }
-
- if(nRank > MAX_POSE_RANK) {
- LogPrint("masternode", "CMasternodeMan::ProcessVerifyBroadcast -- Masternode %s is not in top %d, current rank %d, peer=%d\n",
- mnv.masternodeOutpoint2.ToStringShort(), (int)MAX_POSE_RANK, nRank, pnode->id);
- return;
- }
-
- {
- LOCK(cs);
-
- CMasternode* pmn1 = Find(mnv.masternodeOutpoint1);
- if(!pmn1) {
- LogPrintf("CMasternodeMan::ProcessVerifyBroadcast -- can't find masternode1 %s\n", mnv.masternodeOutpoint1.ToStringShort());
- return;
- }
-
- CMasternode* pmn2 = Find(mnv.masternodeOutpoint2);
- if(!pmn2) {
- LogPrintf("CMasternodeMan::ProcessVerifyBroadcast -- can't find masternode2 %s\n", mnv.masternodeOutpoint2.ToStringShort());
- return;
- }
-
- if(pmn1->addr != mnv.addr) {
- LogPrintf("CMasternodeMan::ProcessVerifyBroadcast -- addr %s does not match %s\n", mnv.addr.ToString(), pmn1->addr.ToString());
- return;
- }
-
- if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
- uint256 hash1 = mnv.GetSignatureHash1(blockHash);
- uint256 hash2 = mnv.GetSignatureHash2(blockHash);
-
- if(!CHashSigner::VerifyHash(hash1, pmn1->legacyKeyIDOperator, mnv.vchSig1, strError)) {
- LogPrintf("MasternodeMan::ProcessVerifyBroadcast -- VerifyHash() failed, error: %s\n", strError);
- return;
- }
-
- if(!CHashSigner::VerifyHash(hash2, pmn2->legacyKeyIDOperator, mnv.vchSig2, strError)) {
- LogPrintf("MasternodeMan::ProcessVerifyBroadcast -- VerifyHash() failed, error: %s\n", strError);
- return;
- }
- } else {
- std::string strMessage1 = strprintf("%s%d%s", mnv.addr.ToString(false), mnv.nonce, blockHash.ToString());
- std::string strMessage2 = strprintf("%s%d%s%s%s", mnv.addr.ToString(false), mnv.nonce, blockHash.ToString(),
- mnv.masternodeOutpoint1.ToStringShort(), mnv.masternodeOutpoint2.ToStringShort());
-
- if(!CMessageSigner::VerifyMessage(pmn1->legacyKeyIDOperator, mnv.vchSig1, strMessage1, strError)) {
- LogPrintf("CMasternodeMan::ProcessVerifyBroadcast -- VerifyMessage() for masternode1 failed, error: %s\n", strError);
- return;
- }
-
- if(!CMessageSigner::VerifyMessage(pmn2->legacyKeyIDOperator, mnv.vchSig2, strMessage2, strError)) {
- LogPrintf("CMasternodeMan::ProcessVerifyBroadcast -- VerifyMessage() for masternode2 failed, error: %s\n", strError);
- return;
- }
- }
-
- if(!pmn1->IsPoSeVerified()) {
- pmn1->DecreasePoSeBanScore();
- }
- mnv.Relay();
-
- LogPrintf("CMasternodeMan::ProcessVerifyBroadcast -- verified masternode %s for addr %s\n",
- pmn1->outpoint.ToStringShort(), pmn1->addr.ToString());
-
- // increase ban score for everyone else with the same addr
- int nCount = 0;
- for (auto& mnpair : mapMasternodes) {
- if(mnpair.second.addr != mnv.addr || mnpair.first == mnv.masternodeOutpoint1) continue;
- mnpair.second.IncreasePoSeBanScore();
- nCount++;
- LogPrint("masternode", "CMasternodeMan::ProcessVerifyBroadcast -- increased PoSe ban score for %s addr %s, new score %d\n",
- mnpair.first.ToStringShort(), mnpair.second.addr.ToString(), mnpair.second.nPoSeBanScore);
- }
- if(nCount)
- LogPrintf("CMasternodeMan::ProcessVerifyBroadcast -- PoSe score increased for %d fake masternodes, addr %s\n",
- nCount, pmn1->addr.ToString());
- }
-}
-
-std::string CMasternodeMan::ToString() const
-{
- std::ostringstream info;
-
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
- info << "Masternodes: masternode object count: " << (int)mapMasternodes.size() <<
- ", deterministic masternode count: " << deterministicMNManager->GetListAtChainTip().GetAllMNsCount() <<
- ", nDsqCount: " << (int)nDsqCount;
- } else {
- info << "Masternodes: " << (int)mapMasternodes.size() <<
- ", peers who asked us for Masternode list: " << (int)mAskedUsForMasternodeList.size() <<
- ", peers we asked for Masternode list: " << (int)mWeAskedForMasternodeList.size() <<
- ", entries in Masternode list we asked for: " << (int)mWeAskedForMasternodeListEntry.size() <<
- ", nDsqCount: " << (int)nDsqCount;
- }
- return info.str();
-}
-
-bool CMasternodeMan::CheckMnbAndUpdateMasternodeList(CNode* pfrom, CMasternodeBroadcast mnb, int& nDos, CConnman& connman)
-{
- // Need to lock cs_main here to ensure consistent locking order because the SimpleCheck call below locks cs_main
- LOCK(cs_main);
-
- if (deterministicMNManager->IsDeterministicMNsSporkActive())
- return false;
-
- {
- LOCK(cs);
- nDos = 0;
- LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- masternode=%s\n", mnb.outpoint.ToStringShort());
-
- uint256 hash = mnb.GetHash();
- if(mapSeenMasternodeBroadcast.count(hash) && !mnb.fRecovery) { //seen
- LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- masternode=%s seen\n", mnb.outpoint.ToStringShort());
- // less then 2 pings left before this MN goes into non-recoverable state, bump sync timeout
- if(GetTime() - mapSeenMasternodeBroadcast[hash].first > MASTERNODE_NEW_START_REQUIRED_SECONDS - MASTERNODE_MIN_MNP_SECONDS * 2) {
- LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- masternode=%s seen update\n", mnb.outpoint.ToStringShort());
- mapSeenMasternodeBroadcast[hash].first = GetTime();
- masternodeSync.BumpAssetLastTime("CMasternodeMan::CheckMnbAndUpdateMasternodeList - seen");
- }
- // did we ask this node for it?
- if(pfrom && IsMnbRecoveryRequested(hash) && GetTime() < mMnbRecoveryRequests[hash].first) {
- LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- mnb=%s seen request\n", hash.ToString());
- if(mMnbRecoveryRequests[hash].second.count(pfrom->addr)) {
- LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- mnb=%s seen request, addr=%s\n", hash.ToString(), pfrom->addr.ToString());
- // do not allow node to send same mnb multiple times in recovery mode
- mMnbRecoveryRequests[hash].second.erase(pfrom->addr);
- // does it have newer lastPing?
- if(mnb.lastPing.sigTime > mapSeenMasternodeBroadcast[hash].second.lastPing.sigTime) {
- // simulate Check
- CMasternode mnTemp = CMasternode(mnb);
- mnTemp.Check();
- LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- mnb=%s seen request, addr=%s, better lastPing: %d min ago, projected mn state: %s\n", hash.ToString(), pfrom->addr.ToString(), (GetAdjustedTime() - mnb.lastPing.sigTime)/60, mnTemp.GetStateString());
- if(mnTemp.IsValidStateForAutoStart(mnTemp.nActiveState)) {
- // this node thinks it's a good one
- LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- masternode=%s seen good\n", mnb.outpoint.ToStringShort());
- mMnbRecoveryGoodReplies[hash].push_back(mnb);
- }
- }
- }
- }
- return true;
- }
- mapSeenMasternodeBroadcast.insert(std::make_pair(hash, std::make_pair(GetTime(), mnb)));
-
- LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- masternode=%s new\n", mnb.outpoint.ToStringShort());
-
- if(!mnb.SimpleCheck(nDos)) {
- LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- SimpleCheck() failed, masternode=%s\n", mnb.outpoint.ToStringShort());
- return false;
- }
-
- // search Masternode list
- CMasternode* pmn = Find(mnb.outpoint);
- if(pmn) {
- CMasternodeBroadcast mnbOld = mapSeenMasternodeBroadcast[CMasternodeBroadcast(*pmn).GetHash()].second;
- if(!mnb.Update(pmn, nDos, connman)) {
- LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- Update() failed, masternode=%s\n", mnb.outpoint.ToStringShort());
- return false;
- }
- if(hash != mnbOld.GetHash()) {
- mapSeenMasternodeBroadcast.erase(mnbOld.GetHash());
- }
- return true;
- }
- }
-
- if(mnb.CheckOutpoint(nDos)) {
- Add(mnb);
- masternodeSync.BumpAssetLastTime("CMasternodeMan::CheckMnbAndUpdateMasternodeList - new");
- // if it matches our Masternode privkey...
- if(fMasternodeMode && mnb.legacyKeyIDOperator == activeMasternodeInfo.legacyKeyIDOperator) {
- mnb.nPoSeBanScore = -MASTERNODE_POSE_BAN_MAX_SCORE;
- if(mnb.nProtocolVersion == PROTOCOL_VERSION) {
- // ... and PROTOCOL_VERSION, then we've been remotely activated ...
- LogPrintf("CMasternodeMan::CheckMnbAndUpdateMasternodeList -- Got NEW Masternode entry: masternode=%s sigTime=%lld addr=%s\n",
- mnb.outpoint.ToStringShort(), mnb.sigTime, mnb.addr.ToString());
- legacyActiveMasternodeManager.ManageState(connman);
- } else {
- // ... otherwise we need to reactivate our node, do not add it to the list and do not relay
- // but also do not ban the node we get this message from
- LogPrintf("CMasternodeMan::CheckMnbAndUpdateMasternodeList -- wrong PROTOCOL_VERSION, re-activate your MN: message nProtocolVersion=%d PROTOCOL_VERSION=%d\n", mnb.nProtocolVersion, PROTOCOL_VERSION);
- return false;
- }
- }
- mnb.Relay(connman);
- } else {
- LogPrintf("CMasternodeMan::CheckMnbAndUpdateMasternodeList -- Rejected Masternode entry: %s addr=%s\n", mnb.outpoint.ToStringShort(), mnb.addr.ToString());
- return false;
- }
-
- return true;
-}
-
-void CMasternodeMan::UpdateLastPaid(const CBlockIndex* pindex)
-{
- LOCK2(cs_main, cs);
-
- if(fLiteMode || !masternodeSync.IsWinnersListSynced() || mapMasternodes.empty()) return;
-
- static int nLastRunBlockHeight = 0;
- // Scan at least LAST_PAID_SCAN_BLOCKS but no more than mnpayments.GetStorageLimit()
- int nMaxBlocksToScanBack = std::max(LAST_PAID_SCAN_BLOCKS, nCachedBlockHeight - nLastRunBlockHeight);
- nMaxBlocksToScanBack = std::min(nMaxBlocksToScanBack, mnpayments.GetStorageLimit());
-
- LogPrint("masternode", "CMasternodeMan::UpdateLastPaid -- nCachedBlockHeight=%d, nLastRunBlockHeight=%d, nMaxBlocksToScanBack=%d\n",
- nCachedBlockHeight, nLastRunBlockHeight, nMaxBlocksToScanBack);
-
- for (auto& mnpair : mapMasternodes) {
- mnpair.second.UpdateLastPaid(pindex, nMaxBlocksToScanBack);
- }
-
- nLastRunBlockHeight = nCachedBlockHeight;
-}
-
-void CMasternodeMan::UpdateLastSentinelPingTime()
-{
- LOCK(cs);
- if (deterministicMNManager->IsDeterministicMNsSporkActive())
- return;
- nLastSentinelPingTime = GetTime();
-}
-
-bool CMasternodeMan::IsSentinelPingActive()
-{
- LOCK(cs);
- // Check if any masternodes have voted recently, otherwise return false
- return (GetTime() - nLastSentinelPingTime) <= MASTERNODE_SENTINEL_PING_MAX_SECONDS;
-}
-
-bool CMasternodeMan::AddGovernanceVote(const COutPoint& outpoint, uint256 nGovernanceObjectHash)
-{
- LOCK(cs);
- CMasternode* pmn = Find(outpoint);
- if(!pmn) {
- return false;
- }
- pmn->AddGovernanceVote(nGovernanceObjectHash);
- return true;
-}
-
-void CMasternodeMan::RemoveGovernanceObject(uint256 nGovernanceObjectHash)
-{
- LOCK(cs);
- for(auto& mnpair : mapMasternodes) {
- mnpair.second.RemoveGovernanceObject(nGovernanceObjectHash);
- }
-}
-
-void CMasternodeMan::CheckMasternode(const CKeyID& keyIDOperator, bool fForce)
-{
- LOCK2(cs_main, cs);
- if (deterministicMNManager->IsDeterministicMNsSporkActive())
- return;
- for (auto& mnpair : mapMasternodes) {
- if (mnpair.second.legacyKeyIDOperator == keyIDOperator) {
- mnpair.second.Check(fForce);
- return;
- }
- }
-}
-
-bool CMasternodeMan::IsMasternodePingedWithin(const COutPoint& outpoint, int nSeconds, int64_t nTimeToCheckAt)
-{
- LOCK(cs);
- CMasternode* pmn = Find(outpoint);
- return pmn ? pmn->IsPingedWithin(nSeconds, nTimeToCheckAt) : false;
-}
-
-void CMasternodeMan::SetMasternodeLastPing(const COutPoint& outpoint, const CMasternodePing& mnp)
-{
- LOCK(cs);
- if (deterministicMNManager->IsDeterministicMNsSporkActive())
- return;
- CMasternode* pmn = Find(outpoint);
- if(!pmn) {
- return;
- }
- pmn->lastPing = mnp;
- if(mnp.fSentinelIsCurrent) {
- UpdateLastSentinelPingTime();
- }
- mapSeenMasternodePing.insert(std::make_pair(mnp.GetHash(), mnp));
-
- CMasternodeBroadcast mnb(*pmn);
- uint256 hash = mnb.GetHash();
- if(mapSeenMasternodeBroadcast.count(hash)) {
- mapSeenMasternodeBroadcast[hash].second.lastPing = mnp;
- }
-}
-
-void CMasternodeMan::UpdatedBlockTip(const CBlockIndex *pindex)
-{
- nCachedBlockHeight = pindex->nHeight;
- LogPrint("masternode", "CMasternodeMan::UpdatedBlockTip -- nCachedBlockHeight=%d\n", nCachedBlockHeight);
-
- AddDeterministicMasternodes();
- RemoveNonDeterministicMasternodes();
-
- CheckSameAddr();
-
- if(fMasternodeMode) {
- // normal wallet does not need to update this every block, doing update on rpc call should be enough
- UpdateLastPaid(pindex);
- }
-}
-
-void CMasternodeMan::WarnMasternodeDaemonUpdates()
-{
- LOCK(cs);
-
- static bool fWarned = false;
-
- if (fWarned || !size() || !masternodeSync.IsMasternodeListSynced())
- return;
-
- int nUpdatedMasternodes{0};
-
- for (const auto& mnpair : mapMasternodes) {
- if (mnpair.second.lastPing.nDaemonVersion > CLIENT_VERSION) {
- ++nUpdatedMasternodes;
- }
- }
-
- // Warn only when at least half of known masternodes already updated
- if (nUpdatedMasternodes < size() / 2)
- return;
-
- std::string strWarning;
- if (nUpdatedMasternodes != size()) {
- strWarning = strprintf(_("Warning: At least %d of %d masternodes are running on a newer software version. Please check latest releases, you might need to update too."),
- nUpdatedMasternodes, size());
- } else {
- // someone was postponing this update for way too long probably
- strWarning = strprintf(_("Warning: Every masternode (out of %d known ones) is running on a newer software version. Please check latest releases, it's very likely that you missed a major/critical update."),
- size());
- }
-
- // notify GetWarnings(), called by Qt and the JSON-RPC code to warn the user
- SetMiscWarning(strWarning);
- // trigger GUI update
- uiInterface.NotifyAlertChanged(SerializeHash(strWarning), CT_NEW);
- // trigger cmd-line notification
- CAlert::Notify(strWarning);
-
- fWarned = true;
-}
-
-void CMasternodeMan::NotifyMasternodeUpdates(CConnman& connman, bool forceAddedChecks, bool forceRemovedChecks)
-{
- // Avoid double locking
- bool fMasternodesAddedLocal = false;
- bool fMasternodesRemovedLocal = false;
- {
- LOCK(cs);
- fMasternodesAddedLocal = fMasternodesAdded;
- fMasternodesRemovedLocal = fMasternodesRemoved;
- }
-
- if(fMasternodesAddedLocal || forceAddedChecks) {
- governance.CheckMasternodeOrphanObjects(connman);
- governance.CheckMasternodeOrphanVotes(connman);
- }
- if(fMasternodesRemovedLocal || forceRemovedChecks) {
- governance.UpdateCachesAndClean();
- }
-
- LOCK(cs);
- fMasternodesAdded = false;
- fMasternodesRemoved = false;
-}
-
-void CMasternodeMan::DoMaintenance(CConnman& connman)
-{
- if(fLiteMode) return; // disable all Dash specific functionality
-
- if(!masternodeSync.IsBlockchainSynced() || ShutdownRequested())
- return;
-
- static unsigned int nTick = 0;
-
- nTick++;
-
- // make sure to check all masternodes first
- mnodeman.Check();
-
- mnodeman.ProcessPendingMnbRequests(connman);
- mnodeman.ProcessPendingMnvRequests(connman);
-
- if(nTick % 60 == 0) {
- mnodeman.ProcessMasternodeConnections(connman);
- mnodeman.CheckAndRemove(connman);
- mnodeman.WarnMasternodeDaemonUpdates();
- }
-
- if(fMasternodeMode && (nTick % (60 * 5) == 0)) {
- mnodeman.DoFullVerificationStep(connman);
- }
-}
diff --git a/src/masternodeman.h b/src/masternodeman.h
deleted file mode 100644
index 853fed868301..000000000000
--- a/src/masternodeman.h
+++ /dev/null
@@ -1,255 +0,0 @@
-// Copyright (c) 2014-2017 The Dash Core developers
-// Distributed under the MIT/X11 software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#ifndef MASTERNODEMAN_H
-#define MASTERNODEMAN_H
-
-#include "masternode.h"
-#include "sync.h"
-
-class CMasternodeMan;
-class CConnman;
-
-extern CMasternodeMan mnodeman;
-
-class CMasternodeMan
-{
-public:
- typedef std::pair score_pair_t;
- typedef std::vector score_pair_vec_t;
- typedef std::pair rank_pair_t;
- typedef std::vector rank_pair_vec_t;
-
-private:
- static const std::string SERIALIZATION_VERSION_STRING;
-
- static const int DSEG_UPDATE_SECONDS = 3 * 60 * 60;
-
- static const int LAST_PAID_SCAN_BLOCKS;
-
- static const int MIN_POSE_PROTO_VERSION = 70203;
- static const int MAX_POSE_CONNECTIONS = 10;
- static const int MAX_POSE_RANK = 10;
- static const int MAX_POSE_BLOCKS = 10;
-
- static const int MNB_RECOVERY_QUORUM_TOTAL = 10;
- static const int MNB_RECOVERY_QUORUM_REQUIRED = 6;
- static const int MNB_RECOVERY_MAX_ASK_ENTRIES = 10;
- static const int MNB_RECOVERY_WAIT_SECONDS = 60;
- static const int MNB_RECOVERY_RETRY_SECONDS = 3 * 60 * 60;
-
-
- // critical section to protect the inner data structures
- mutable CCriticalSection cs;
-
- // Keep track of current block height
- int nCachedBlockHeight;
-
- // map to hold all MNs
- std::map mapMasternodes;
- // who's asked for the Masternode list and the last time
- std::map mAskedUsForMasternodeList;
- // who we asked for the Masternode list and the last time
- std::map mWeAskedForMasternodeList;
- // which Masternodes we've asked for
- std::map > mWeAskedForMasternodeListEntry;
-
- // who we asked for the masternode verification
- std::map mWeAskedForVerification;
-
- // these maps are used for masternode recovery from MASTERNODE_NEW_START_REQUIRED state
- std::map > > mMnbRecoveryRequests;
- std::map > mMnbRecoveryGoodReplies;
- std::list< std::pair > listScheduledMnbRequestConnections;
- std::map > > mapPendingMNB;
- std::map > mapPendingMNV;
- CCriticalSection cs_mapPendingMNV;
-
- /// Set when masternodes are added, cleared when CGovernanceManager is notified
- bool fMasternodesAdded;
-
- /// Set when masternodes are removed, cleared when CGovernanceManager is notified
- bool fMasternodesRemoved;
-
- std::vector vecDirtyGovernanceObjectHashes;
-
- int64_t nLastSentinelPingTime;
-
- friend class CMasternodeSync;
- /// Find an entry
- CMasternode* Find(const COutPoint& outpoint);
-
- bool GetMasternodeScores(const uint256& nBlockHash, score_pair_vec_t& vecMasternodeScoresRet, int nMinProtocol = 0);
-
- void SyncSingle(CNode* pnode, const COutPoint& outpoint, CConnman& connman);
- void SyncAll(CNode* pnode, CConnman& connman);
-
- void PushDsegInvs(CNode* pnode, const CMasternode& mn);
-
-public:
- // Keep track of all broadcasts I've seen
- std::map > mapSeenMasternodeBroadcast;
- // Keep track of all pings I've seen
- std::map mapSeenMasternodePing;
- // Keep track of all verifications I've seen
- std::map mapSeenMasternodeVerification;
- // keep track of dsq count to prevent masternodes from gaming privatesend queue
- int64_t nDsqCount;
-
-
- ADD_SERIALIZE_METHODS;
-
- template
- inline void SerializationOp(Stream& s, Operation ser_action) {
- LOCK(cs);
- std::string strVersion;
- if(ser_action.ForRead()) {
- READWRITE(strVersion);
- }
- else {
- strVersion = SERIALIZATION_VERSION_STRING;
- READWRITE(strVersion);
- }
-
- READWRITE(mapMasternodes);
- READWRITE(mAskedUsForMasternodeList);
- READWRITE(mWeAskedForMasternodeList);
- READWRITE(mWeAskedForMasternodeListEntry);
- READWRITE(mMnbRecoveryRequests);
- READWRITE(mMnbRecoveryGoodReplies);
- READWRITE(nLastSentinelPingTime);
- READWRITE(nDsqCount);
-
- READWRITE(mapSeenMasternodeBroadcast);
- READWRITE(mapSeenMasternodePing);
- if(ser_action.ForRead() && (strVersion != SERIALIZATION_VERSION_STRING)) {
- Clear();
- }
- }
-
- CMasternodeMan();
-
- /// Add an entry
- bool Add(CMasternode &mn);
-
- /// Ask (source) node for mnb
- void AskForMN(CNode *pnode, const COutPoint& outpoint, CConnman& connman);
-
- bool PoSeBan(const COutPoint &outpoint);
- bool AllowMixing(const COutPoint &outpoint);
- bool DisallowMixing(const COutPoint &outpoint);
-
- /// Check all Masternodes
- void Check();
-
- /// Check all Masternodes and remove inactive
- void CheckAndRemove(CConnman& connman);
- /// This is dummy overload to be used for dumping/loading mncache.dat
- void CheckAndRemove() {}
-
- void AddDeterministicMasternodes();
- void RemoveNonDeterministicMasternodes();
-
- /// Clear Masternode vector
- void Clear();
-
- /// Count Masternodes filtered by nProtocolVersion.
- /// Masternode nProtocolVersion should match or be above the one specified in param here.
- int CountMasternodes(int nProtocolVersion = -1);
- /// Count enabled Masternodes filtered by nProtocolVersion.
- /// Masternode nProtocolVersion should match or be above the one specified in param here.
- int CountEnabled(int nProtocolVersion = -1);
-
- /// Count Masternodes by network type - NET_IPV4, NET_IPV6, NET_TOR
- // int CountByIP(int nNetworkType);
-
- void DsegUpdate(CNode* pnode, CConnman& connman);
-
- /// Versions of Find that are safe to use from outside the class
- bool Get(const COutPoint& outpoint, CMasternode& masternodeRet);
- bool Has(const COutPoint& outpoint);
-
- bool GetMasternodeInfo(const uint256& proTxHash, masternode_info_t& mnInfoRet);
- bool GetMasternodeInfo(const COutPoint& outpoint, masternode_info_t& mnInfoRet);
- bool GetMasternodeInfo(const CKeyID& keyIDOperator, masternode_info_t& mnInfoRet);
- bool GetMasternodeInfo(const CScript& payee, masternode_info_t& mnInfoRet);
-
- /// Find an entry in the masternode list that is next to be paid
- bool GetNextMasternodeInQueueForPayment(int nBlockHeight, bool fFilterSigTime, int& nCountRet, masternode_info_t& mnInfoRet);
- /// Same as above but use current block height
- bool GetNextMasternodeInQueueForPayment(bool fFilterSigTime, int& nCountRet, masternode_info_t& mnInfoRet);
-
- /// Find a random entry
- masternode_info_t FindRandomNotInVec(const std::vector &vecToExclude, int nProtocolVersion = -1);
-
- std::map GetFullMasternodeMap();
-
- bool GetMasternodeRanks(rank_pair_vec_t& vecMasternodeRanksRet, int nBlockHeight = -1, int nMinProtocol = 0);
- bool GetMasternodeRank(const COutPoint &outpoint, int& nRankRet, int nBlockHeight = -1, int nMinProtocol = 0);
- bool GetMasternodeRank(const COutPoint &outpoint, int& nRankRet, uint256& blockHashRet, int nBlockHeight = -1, int nMinProtocol = 0);
-
- void ProcessMasternodeConnections(CConnman& connman);
- std::pair > PopScheduledMnbRequestConnection();
- void ProcessPendingMnbRequests(CConnman& connman);
-
- void ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, CConnman& connman);
-
- void DoFullVerificationStep(CConnman& connman);
- void CheckSameAddr();
- bool CheckVerifyRequestAddr(const CAddress& addr, CConnman& connman);
- void PrepareVerifyRequest(const CAddress& addr, CConnman& connman);
- void ProcessPendingMnvRequests(CConnman& connman);
- void SendVerifyReply(CNode* pnode, CMasternodeVerification& mnv, CConnman& connman);
- void ProcessVerifyReply(CNode* pnode, CMasternodeVerification& mnv);
- void ProcessVerifyBroadcast(CNode* pnode, const CMasternodeVerification& mnv);
-
- /// Return the number of (unique) Masternodes
- int size() { return mapMasternodes.size(); }
-
- std::string ToString() const;
-
- /// Perform complete check and only then update masternode list and maps using provided CMasternodeBroadcast
- bool CheckMnbAndUpdateMasternodeList(CNode* pfrom, CMasternodeBroadcast mnb, int& nDos, CConnman& connman);
- bool IsMnbRecoveryRequested(const uint256& hash) { return mMnbRecoveryRequests.count(hash); }
-
- void UpdateLastPaid(const CBlockIndex* pindex);
-
- void AddDirtyGovernanceObjectHash(const uint256& nHash)
- {
- LOCK(cs);
- vecDirtyGovernanceObjectHashes.push_back(nHash);
- }
-
- std::vector GetAndClearDirtyGovernanceObjectHashes()
- {
- LOCK(cs);
- std::vector vecTmp = vecDirtyGovernanceObjectHashes;
- vecDirtyGovernanceObjectHashes.clear();
- return vecTmp;
- }
-
- bool IsSentinelPingActive();
- void UpdateLastSentinelPingTime();
- bool AddGovernanceVote(const COutPoint& outpoint, uint256 nGovernanceObjectHash);
- void RemoveGovernanceObject(uint256 nGovernanceObjectHash);
-
- void CheckMasternode(const CKeyID& keyIDOperator, bool fForce);
-
- bool IsMasternodePingedWithin(const COutPoint& outpoint, int nSeconds, int64_t nTimeToCheckAt = -1);
- void SetMasternodeLastPing(const COutPoint& outpoint, const CMasternodePing& mnp);
-
- void UpdatedBlockTip(const CBlockIndex *pindex);
-
- void WarnMasternodeDaemonUpdates();
-
- /**
- * Called to notify CGovernanceManager that the masternode index has been updated.
- * Must be called while not holding the CMasternodeMan::cs mutex
- */
- void NotifyMasternodeUpdates(CConnman& connman, bool forceAddedChecks = false, bool forceRemovedChecks = false);
-
- void DoMaintenance(CConnman &connman);
-};
-
-#endif
diff --git a/src/net.cpp b/src/net.cpp
index 651e672c0d60..44e068e7e3fd 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -23,10 +23,10 @@
#include "scheduler.h"
#include "ui_interface.h"
#include "utilstrencodings.h"
+#include "validation.h"
#include "instantx.h"
#include "masternode-sync.h"
-#include "masternodeman.h"
#include "privatesend.h"
#ifdef WIN32
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index 3010fbd78108..f6e6a294e32c 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -36,7 +36,7 @@
#include "instantx.h"
#include "masternode-payments.h"
#include "masternode-sync.h"
-#include "masternodeman.h"
+#include "masternode-meta.h"
#ifdef ENABLE_WALLET
#include "privatesend-client.h"
#endif // ENABLE_WALLET
@@ -940,21 +940,6 @@ bool static AlreadyHave(const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
return sporkManager.GetSporkByHash(inv.hash, spork);
}
- case MSG_MASTERNODE_PAYMENT_VOTE:
- return mnpayments.mapMasternodePaymentVotes.count(inv.hash);
-
- case MSG_MASTERNODE_PAYMENT_BLOCK:
- {
- BlockMap::iterator mi = mapBlockIndex.find(inv.hash);
- return mi != mapBlockIndex.end() && mnpayments.mapMasternodeBlocks.find(mi->second->nHeight) != mnpayments.mapMasternodeBlocks.end();
- }
-
- case MSG_MASTERNODE_ANNOUNCE:
- return mnodeman.mapSeenMasternodeBroadcast.count(inv.hash) && !mnodeman.IsMnbRecoveryRequested(inv.hash);
-
- case MSG_MASTERNODE_PING:
- return mnodeman.mapSeenMasternodePing.count(inv.hash);
-
case MSG_DSTX: {
return static_cast(CPrivateSend::GetDSTX(inv.hash));
}
@@ -963,9 +948,6 @@ bool static AlreadyHave(const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
case MSG_GOVERNANCE_OBJECT_VOTE:
return ! governance.ConfirmInventoryRequest(inv);
- case MSG_MASTERNODE_VERIFY:
- return mnodeman.mapSeenMasternodeVerification.count(inv.hash);
-
case MSG_QUORUM_FINAL_COMMITMENT:
return llmq::quorumBlockProcessor->HasMinableCommitment(inv.hash);
case MSG_QUORUM_DUMMY_COMMITMENT:
@@ -1188,51 +1170,6 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
}
}
- if (!push && inv.type == MSG_MASTERNODE_PAYMENT_VOTE) {
- if (!deterministicMNManager->IsDeterministicMNsSporkActive()) {
- if (mnpayments.HasVerifiedPaymentVote(inv.hash)) {
- connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::MASTERNODEPAYMENTVOTE, mnpayments.mapMasternodePaymentVotes[inv.hash]));
- push = true;
- }
- }
- }
-
- if (!push && inv.type == MSG_MASTERNODE_PAYMENT_BLOCK) {
- if (!deterministicMNManager->IsDeterministicMNsSporkActive()) {
- BlockMap::iterator mi = mapBlockIndex.find(inv.hash);
- LOCK(cs_mapMasternodeBlocks);
- if (mi != mapBlockIndex.end() && mnpayments.mapMasternodeBlocks.count(mi->second->nHeight)) {
- BOOST_FOREACH(CMasternodePayee& payee, mnpayments.mapMasternodeBlocks[mi->second->nHeight].vecPayees) {
- std::vector vecVoteHashes = payee.GetVoteHashes();
- BOOST_FOREACH(uint256& hash, vecVoteHashes) {
- if(mnpayments.HasVerifiedPaymentVote(hash)) {
- connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::MASTERNODEPAYMENTVOTE, mnpayments.mapMasternodePaymentVotes[hash]));
- }
- }
- }
- push = true;
- }
- }
- }
-
- if (!push && inv.type == MSG_MASTERNODE_ANNOUNCE) {
- if (!deterministicMNManager->IsDeterministicMNsSporkActive()) {
- if (mnodeman.mapSeenMasternodeBroadcast.count(inv.hash)) {
- connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::MNANNOUNCE, mnodeman.mapSeenMasternodeBroadcast[inv.hash].second));
- push = true;
- }
- }
- }
-
- if (!push && inv.type == MSG_MASTERNODE_PING) {
- if (!deterministicMNManager->IsDeterministicMNsSporkActive()) {
- if (mnodeman.mapSeenMasternodePing.count(inv.hash)) {
- connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::MNPING, mnodeman.mapSeenMasternodePing[inv.hash]));
- push = true;
- }
- }
- }
-
if (!push && inv.type == MSG_DSTX) {
CPrivateSendBroadcastTx dstx = CPrivateSend::GetDSTX(inv.hash);
if(dstx) {
@@ -1278,13 +1215,6 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
}
}
- if (!push && inv.type == MSG_MASTERNODE_VERIFY) {
- if(mnodeman.mapSeenMasternodeVerification.count(inv.hash)) {
- connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::MNVERIFY, mnodeman.mapSeenMasternodeVerification[inv.hash]));
- push = true;
- }
- }
-
if (!push && (inv.type == MSG_QUORUM_FINAL_COMMITMENT)) {
llmq::CFinalCommitment o;
if (llmq::quorumBlockProcessor->GetMinableCommitmentByHash(inv.hash, o)) {
@@ -1796,20 +1726,9 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
}
else
{
- static std::set legacyMNObjs = {
- MSG_MASTERNODE_PAYMENT_VOTE,
- MSG_MASTERNODE_PAYMENT_BLOCK,
- MSG_MASTERNODE_ANNOUNCE,
- MSG_MASTERNODE_PING,
- MSG_MASTERNODE_VERIFY,
- };
static std::set allowWhileInIBDObjs = {
MSG_SPORK
};
- if (legacyMNObjs.count(inv.type) && deterministicMNManager->IsDeterministicMNsSporkActive()) {
- LogPrint("net", "ignoring (%s) inv of legacy type %d peer=%d\n", inv.hash.ToString(), inv.type, pfrom->id);
- continue;
- }
pfrom->AddInventoryKnown(inv);
if (fBlocksOnly) {
@@ -2079,28 +1998,27 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
return true; // not an error
}
- CMasternode mn;
-
- if(!mnodeman.Get(dstx.masternodeOutpoint, mn)) {
+ auto dmn = deterministicMNManager->GetListAtChainTip().GetValidMNByCollateral(dstx.masternodeOutpoint);
+ if(!dmn) {
LogPrint("privatesend", "DSTX -- Can't find masternode %s to verify %s\n", dstx.masternodeOutpoint.ToStringShort(), hashTx.ToString());
return false;
}
- if(!mn.IsValidForMixingTxes()) {
+ if (!mmetaman.GetMetaInfo(dmn->proTxHash)->IsValidForMixingTxes()) {
LogPrint("privatesend", "DSTX -- Masternode %s is sending too many transactions %s\n", dstx.masternodeOutpoint.ToStringShort(), hashTx.ToString());
return true;
// TODO: Not an error? Could it be that someone is relaying old DSTXes
// we have no idea about (e.g we were offline)? How to handle them?
}
- if (!dstx.CheckSignature(mn.legacyKeyIDOperator, mn.blsPubKeyOperator)) {
+ if (!dstx.CheckSignature(dmn->pdmnState->pubKeyOperator)) {
LogPrint("privatesend", "DSTX -- CheckSignature() failed for %s\n", hashTx.ToString());
return false;
}
LogPrintf("DSTX -- Got Masternode transaction %s\n", hashTx.ToString());
mempool.PrioritiseTransaction(hashTx, hashTx.ToString(), 1000, 0.1*COIN);
- mnodeman.DisallowMixing(dstx.masternodeOutpoint);
+ mmetaman.DisallowMixing(dmn->proTxHash);
}
LOCK(cs_main);
@@ -2974,8 +2892,6 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
privateSendClient.ProcessMessage(pfrom, strCommand, vRecv, connman);
#endif // ENABLE_WALLET
privateSendServer.ProcessMessage(pfrom, strCommand, vRecv, connman);
- mnodeman.ProcessMessage(pfrom, strCommand, vRecv, connman);
- mnpayments.ProcessMessage(pfrom, strCommand, vRecv, connman);
instantsend.ProcessMessage(pfrom, strCommand, vRecv, connman);
sporkManager.ProcessSpork(pfrom, strCommand, vRecv, connman);
masternodeSync.ProcessMessage(pfrom, strCommand, vRecv);
diff --git a/src/privatesend-client.cpp b/src/privatesend-client.cpp
index 13b43e97f821..ee112a9b1a31 100644
--- a/src/privatesend-client.cpp
+++ b/src/privatesend-client.cpp
@@ -9,12 +9,13 @@
#include "init.h"
#include "masternode-payments.h"
#include "masternode-sync.h"
-#include "masternodeman.h"
+#include "masternode-meta.h"
#include "netmessagemaker.h"
#include "script/sign.h"
#include "txmempool.h"
#include "util.h"
#include "utilmoneystr.h"
+#include "validation.h"
#include "wallet/coincontrol.h"
#include
@@ -61,12 +62,12 @@ void CPrivateSendClientManager::ProcessMessage(CNode* pfrom, const std::string&
if (dsq.IsExpired()) return;
- masternode_info_t infoMn;
- if (!mnodeman.GetMasternodeInfo(dsq.masternodeOutpoint, infoMn)) return;
+ auto mnList = deterministicMNManager->GetListAtChainTip();
+ auto dmn = mnList.GetValidMNByCollateral(dsq.masternodeOutpoint);
+ if (!dmn) return;
- if (!dsq.CheckSignature(infoMn.legacyKeyIDOperator, infoMn.blsPubKeyOperator)) {
- // we probably have outdated info
- mnodeman.AskForMN(pfrom, dsq.masternodeOutpoint, connman);
+ if (!dsq.CheckSignature(dmn->pdmnState->pubKeyOperator)) {
+ // TODO ban?
return;
}
@@ -74,9 +75,9 @@ void CPrivateSendClientManager::ProcessMessage(CNode* pfrom, const std::string&
if (dsq.fReady) {
LOCK(cs_deqsessions);
for (auto& session : deqSessions) {
- masternode_info_t mnMixing;
- if (session.GetMixingMasternodeInfo(mnMixing) && mnMixing.addr == infoMn.addr && session.GetState() == POOL_STATE_QUEUE) {
- LogPrint("privatesend", "DSQUEUE -- PrivateSend queue (%s) is ready on masternode %s\n", dsq.ToString(), infoMn.addr.ToString());
+ CDeterministicMNCPtr mnMixing;
+ if (session.GetMixingMasternodeInfo(mnMixing) && mnMixing->pdmnState->addr == dmn->pdmnState->addr && session.GetState() == POOL_STATE_QUEUE) {
+ LogPrint("privatesend", "DSQUEUE -- PrivateSend queue (%s) is ready on masternode %s\n", dsq.ToString(), dmn->pdmnState->addr.ToString());
session.SubmitDenominate(connman);
return;
}
@@ -89,25 +90,26 @@ void CPrivateSendClientManager::ProcessMessage(CNode* pfrom, const std::string&
for (const auto& q : vecPrivateSendQueue) {
if (q.masternodeOutpoint == dsq.masternodeOutpoint) {
// no way same mn can send another "not yet ready" dsq this soon
- LogPrint("privatesend", "DSQUEUE -- Masternode %s is sending WAY too many dsq messages\n", infoMn.addr.ToString());
+ LogPrint("privatesend", "DSQUEUE -- Masternode %s is sending WAY too many dsq messages\n", dmn->pdmnState->ToString());
return;
}
}
- int nThreshold = infoMn.nLastDsq + mnodeman.CountMasternodes() / 5;
- LogPrint("privatesend", "DSQUEUE -- nLastDsq: %d threshold: %d nDsqCount: %d\n", infoMn.nLastDsq, nThreshold, mnodeman.nDsqCount);
+ int64_t nLastDsq = mmetaman.GetMetaInfo(dmn->proTxHash)->GetLastDsq();
+ int nThreshold = nLastDsq + mnList.GetValidMNsCount() / 5;
+ LogPrint("privatesend", "DSQUEUE -- nLastDsq: %d threshold: %d nDsqCount: %d\n", nLastDsq, nThreshold, mmetaman.GetDsqCount());
//don't allow a few nodes to dominate the queuing process
- if (infoMn.nLastDsq != 0 && nThreshold > mnodeman.nDsqCount) {
- LogPrint("privatesend", "DSQUEUE -- Masternode %s is sending too many dsq messages\n", infoMn.addr.ToString());
+ if (nLastDsq != 0 && nThreshold > mmetaman.GetDsqCount()) {
+ LogPrint("privatesend", "DSQUEUE -- Masternode %s is sending too many dsq messages\n", dmn->proTxHash.ToString());
return;
}
- if (!mnodeman.AllowMixing(dsq.masternodeOutpoint)) return;
+ mmetaman.AllowMixing(dmn->proTxHash);
- LogPrint("privatesend", "DSQUEUE -- new PrivateSend queue (%s) from masternode %s\n", dsq.ToString(), infoMn.addr.ToString());
+ LogPrint("privatesend", "DSQUEUE -- new PrivateSend queue (%s) from masternode %s\n", dsq.ToString(), dmn->pdmnState->addr.ToString());
for (auto& session : deqSessions) {
- masternode_info_t mnMixing;
- if (session.GetMixingMasternodeInfo(mnMixing) && mnMixing.outpoint == dsq.masternodeOutpoint) {
+ CDeterministicMNCPtr mnMixing;
+ if (session.GetMixingMasternodeInfo(mnMixing) && mnMixing->collateralOutpoint == dsq.masternodeOutpoint) {
dsq.fTried = true;
}
}
@@ -139,8 +141,8 @@ void CPrivateSendClientSession::ProcessMessage(CNode* pfrom, const std::string&
return;
}
- if (!infoMixingMasternode.fInfoValid) return;
- if (infoMixingMasternode.addr != pfrom->addr) {
+ if (!mixingMasternode) return;
+ if (mixingMasternode->pdmnState->addr != pfrom->addr) {
//LogPrintf("DSSTATUSUPDATE -- message doesn't match current Masternode: infoMixingMasternode %s addr %s\n", infoMixingMasternode.addr.ToString(), pfrom->addr.ToString());
return;
}
@@ -181,8 +183,8 @@ void CPrivateSendClientSession::ProcessMessage(CNode* pfrom, const std::string&
return;
}
- if (!infoMixingMasternode.fInfoValid) return;
- if (infoMixingMasternode.addr != pfrom->addr) {
+ if (!mixingMasternode) return;
+ if (mixingMasternode->pdmnState->addr != pfrom->addr) {
//LogPrintf("DSFINALTX -- message doesn't match current Masternode: infoMixingMasternode %s addr %s\n", infoMixingMasternode.addr.ToString(), pfrom->addr.ToString());
return;
}
@@ -208,9 +210,9 @@ void CPrivateSendClientSession::ProcessMessage(CNode* pfrom, const std::string&
return;
}
- if (!infoMixingMasternode.fInfoValid) return;
- if (infoMixingMasternode.addr != pfrom->addr) {
- LogPrint("privatesend", "DSCOMPLETE -- message doesn't match current Masternode: infoMixingMasternode=%s addr=%s\n", infoMixingMasternode.addr.ToString(), pfrom->addr.ToString());
+ if (!mixingMasternode) return;
+ if (mixingMasternode->pdmnState->addr != pfrom->addr) {
+ LogPrint("privatesend", "DSCOMPLETE -- message doesn't match current Masternode: infoMixingMasternode=%s addr=%s\n", mixingMasternode->pdmnState->addr.ToString(), pfrom->addr.ToString());
return;
}
@@ -258,7 +260,7 @@ void CPrivateSendClientSession::SetNull()
// Client side
nEntriesCount = 0;
fLastEntryAccepted = false;
- infoMixingMasternode = masternode_info_t();
+ mixingMasternode = nullptr;
pendingDsaRequest = CPendingDsaRequest();
CPrivateSendBaseSession::SetNull();
@@ -368,22 +370,22 @@ std::string CPrivateSendClientManager::GetSessionDenoms()
return strSessionDenoms.empty() ? "N/A" : strSessionDenoms;
}
-bool CPrivateSendClientSession::GetMixingMasternodeInfo(masternode_info_t& mnInfoRet) const
+bool CPrivateSendClientSession::GetMixingMasternodeInfo(CDeterministicMNCPtr& ret) const
{
- mnInfoRet = infoMixingMasternode.fInfoValid ? infoMixingMasternode : masternode_info_t();
- return infoMixingMasternode.fInfoValid;
+ ret = mixingMasternode;
+ return ret != nullptr;
}
-bool CPrivateSendClientManager::GetMixingMasternodesInfo(std::vector& vecMnInfoRet) const
+bool CPrivateSendClientManager::GetMixingMasternodesInfo(std::vector& vecDmnsRet) const
{
LOCK(cs_deqsessions);
for (const auto& session : deqSessions) {
- masternode_info_t mnInfo;
- if (session.GetMixingMasternodeInfo(mnInfo)) {
- vecMnInfoRet.push_back(mnInfo);
+ CDeterministicMNCPtr dmn;
+ if (session.GetMixingMasternodeInfo(dmn)) {
+ vecDmnsRet.push_back(dmn);
}
}
- return !vecMnInfoRet.empty();
+ return !vecDmnsRet.empty();
}
//
@@ -578,7 +580,7 @@ bool CPrivateSendClientSession::SignFinalTransaction(const CTransaction& finalTr
if (!pwalletMain) return false;
if (fMasternodeMode || pnode == nullptr) return false;
- if (!infoMixingMasternode.fInfoValid) return false;
+ if (!mixingMasternode) return false;
finalMutableTransaction = finalTransactionNew;
LogPrintf("CPrivateSendClientSession::SignFinalTransaction -- finalMutableTransaction=%s", finalMutableTransaction.ToString());
@@ -588,7 +590,7 @@ bool CPrivateSendClientSession::SignFinalTransaction(const CTransaction& finalTr
sort(finalMutableTransaction.vout.begin(), finalMutableTransaction.vout.end(), CompareOutputBIP69());
if (finalMutableTransaction.GetHash() != finalTransactionNew.GetHash()) {
- LogPrintf("CPrivateSendClientSession::SignFinalTransaction -- WARNING! Masternode %s is not BIP69 compliant!\n", infoMixingMasternode.outpoint.ToStringShort());
+ LogPrintf("CPrivateSendClientSession::SignFinalTransaction -- WARNING! Masternode %s is not BIP69 compliant!\n", mixingMasternode->proTxHash.ToString());
UnlockCoins();
keyHolderStorage.ReturnAll();
SetNull();
@@ -711,7 +713,7 @@ void CPrivateSendClientManager::AddSkippedDenom(const CAmount& nDenomValue)
bool CPrivateSendClientManager::WaitForAnotherBlock()
{
- if (!masternodeSync.IsMasternodeListSynced())
+ if (!masternodeSync.IsBlockchainSynced())
return true;
if (fPrivateSendMultiSession)
@@ -800,7 +802,7 @@ bool CPrivateSendClientSession::DoAutomaticDenominating(CConnman& connman, bool
if (fMasternodeMode) return false; // no client-side mixing on masternodes
if (nState != POOL_STATE_IDLE) return false;
- if (!masternodeSync.IsMasternodeListSynced()) {
+ if (!masternodeSync.IsBlockchainSynced()) {
strAutoDenomResult = _("Can't mix while sync in progress.");
return false;
}
@@ -832,7 +834,7 @@ bool CPrivateSendClientSession::DoAutomaticDenominating(CConnman& connman, bool
return false;
}
- if (mnodeman.size() == 0) {
+ if (deterministicMNManager->GetListAtChainTip().GetValidMNsCount() == 0) {
LogPrint("privatesend", "CPrivateSendClientSession::DoAutomaticDenominating -- No Masternodes detected\n");
strAutoDenomResult = _("No Masternodes detected.");
return false;
@@ -937,7 +939,7 @@ bool CPrivateSendClientManager::DoAutomaticDenominating(CConnman& connman, bool
if (fMasternodeMode) return false; // no client-side mixing on masternodes
if (!fEnablePrivateSend) return false;
- if (!masternodeSync.IsMasternodeListSynced()) {
+ if (!masternodeSync.IsBlockchainSynced()) {
strAutoDenomResult = _("Can't mix while sync in progress.");
return false;
}
@@ -952,7 +954,7 @@ bool CPrivateSendClientManager::DoAutomaticDenominating(CConnman& connman, bool
return false;
}
- int nMnCountEnabled = mnodeman.CountEnabled(MIN_PRIVATESEND_PEER_PROTO_VERSION);
+ int nMnCountEnabled = deterministicMNManager->GetListAtChainTip().GetValidMNsCount();
// If we've used 90% of the Masternode list then drop the oldest first ~30%
int nThreshold_high = nMnCountEnabled * 0.9;
@@ -990,31 +992,65 @@ void CPrivateSendClientManager::AddUsedMasternode(const COutPoint& outpointMn)
vecMasternodesUsed.push_back(outpointMn);
}
-masternode_info_t CPrivateSendClientManager::GetNotUsedMasternode()
+CDeterministicMNCPtr CPrivateSendClientManager::GetRandomNotUsedMasternode()
{
- return mnodeman.FindRandomNotInVec(vecMasternodesUsed, MIN_PRIVATESEND_PEER_PROTO_VERSION);
+ auto mnList = deterministicMNManager->GetListAtChainTip();
+
+ int nCountEnabled = mnList.GetValidMNsCount();
+ int nCountNotExcluded = nCountEnabled - vecMasternodesUsed.size();
+
+ LogPrintf("CPrivateSendClientManager::%s -- %d enabled masternodes, %d masternodes to choose from\n", __func__, nCountEnabled, nCountNotExcluded);
+ if(nCountNotExcluded < 1) {
+ return nullptr;
+ }
+
+ // fill a vector
+ std::vector vpMasternodesShuffled;
+ vpMasternodesShuffled.reserve((size_t)nCountEnabled);
+ mnList.ForEachMN(true, [&](const CDeterministicMNCPtr& dmn) {
+ vpMasternodesShuffled.emplace_back(dmn);
+ });
+
+ FastRandomContext insecure_rand;
+ // shuffle pointers
+ std::random_shuffle(vpMasternodesShuffled.begin(), vpMasternodesShuffled.end(), insecure_rand);
+
+ std::set excludeSet(vecMasternodesUsed.begin(), vecMasternodesUsed.end());
+
+ // loop through
+ for (const auto& dmn : vpMasternodesShuffled) {
+ if (excludeSet.count(dmn->collateralOutpoint)) {
+ continue;
+ }
+
+ LogPrint("masternode", "CPrivateSendClientManager::%s -- found, masternode=%s\n", __func__, dmn->collateralOutpoint.ToStringShort());
+ return dmn;
+ }
+
+ LogPrint("masternode", "CPrivateSendClientManager::%s -- failed\n", __func__);
+ return nullptr;
}
bool CPrivateSendClientSession::JoinExistingQueue(CAmount nBalanceNeedsAnonymized, CConnman& connman)
{
if (!pwalletMain) return false;
+ auto mnList = deterministicMNManager->GetListAtChainTip();
+
std::vector vecStandardDenoms = CPrivateSend::GetStandardDenominations();
// Look through the queues and see if anything matches
CPrivateSendQueue dsq;
while (privateSendClient.GetQueueItemAndTry(dsq)) {
- masternode_info_t infoMn;
+ auto dmn = mnList.GetValidMNByCollateral(dsq.masternodeOutpoint);
- if (!mnodeman.GetMasternodeInfo(dsq.masternodeOutpoint, infoMn)) {
+ if (!dmn) {
LogPrintf("CPrivateSendClientSession::JoinExistingQueue -- dsq masternode is not in masternode list, masternode=%s\n", dsq.masternodeOutpoint.ToStringShort());
continue;
}
- if (infoMn.nProtocolVersion < MIN_PRIVATESEND_PEER_PROTO_VERSION) continue;
-
// skip next mn payments winners
- if (mnpayments.IsScheduled(infoMn, 0)) {
- LogPrintf("CPrivateSendClientSession::JoinExistingQueue -- skipping winner, masternode=%s\n", infoMn.outpoint.ToStringShort());
+ if (mnpayments.IsScheduled(dmn, 0)) {
+ LogPrintf("CPrivateSendClientSession::JoinExistingQueue -- skipping winner, masternode=%s\n", dmn->proTxHash.ToString());
continue;
}
@@ -1042,20 +1078,20 @@ bool CPrivateSendClientSession::JoinExistingQueue(CAmount nBalanceNeedsAnonymize
privateSendClient.AddUsedMasternode(dsq.masternodeOutpoint);
- if (connman.IsMasternodeOrDisconnectRequested(infoMn.addr)) {
- LogPrintf("CPrivateSendClientSession::JoinExistingQueue -- skipping masternode connection, addr=%s\n", infoMn.addr.ToString());
+ if (connman.IsMasternodeOrDisconnectRequested(dmn->pdmnState->addr)) {
+ LogPrintf("CPrivateSendClientSession::JoinExistingQueue -- skipping masternode connection, addr=%s\n", dmn->pdmnState->addr.ToString());
continue;
}
nSessionDenom = dsq.nDenom;
- infoMixingMasternode = infoMn;
- pendingDsaRequest = CPendingDsaRequest(infoMn.addr, CPrivateSendAccept(nSessionDenom, txMyCollateral));
- connman.AddPendingMasternode(infoMn.addr);
+ mixingMasternode = dmn;
+ pendingDsaRequest = CPendingDsaRequest(dmn->pdmnState->addr, CPrivateSendAccept(nSessionDenom, txMyCollateral));
+ connman.AddPendingMasternode(dmn->pdmnState->addr);
// TODO: add new state POOL_STATE_CONNECTING and bump MIN_PRIVATESEND_PEER_PROTO_VERSION
SetState(POOL_STATE_QUEUE);
nTimeLastSuccessfulStep = GetTime();
LogPrintf("CPrivateSendClientSession::JoinExistingQueue -- pending connection (from queue): nSessionDenom: %d (%s), addr=%s\n",
- nSessionDenom, CPrivateSend::GetDenominationsToString(nSessionDenom), infoMn.addr.ToString());
+ nSessionDenom, CPrivateSend::GetDenominationsToString(nSessionDenom), dmn->pdmnState->addr.ToString());
strAutoDenomResult = _("Trying to connect...");
return true;
}
@@ -1068,7 +1104,7 @@ bool CPrivateSendClientSession::StartNewQueue(CAmount nValueMin, CAmount nBalanc
if (!pwalletMain) return false;
int nTries = 0;
- int nMnCount = mnodeman.CountMasternodes();
+ int nMnCount = deterministicMNManager->GetListAtChainTip().GetValidMNsCount();
// ** find the coins we'll use
std::vector vecTxIn;
@@ -1082,39 +1118,40 @@ bool CPrivateSendClientSession::StartNewQueue(CAmount nValueMin, CAmount nBalanc
// otherwise, try one randomly
while (nTries < 10) {
- masternode_info_t infoMn = privateSendClient.GetNotUsedMasternode();
+ auto dmn = privateSendClient.GetRandomNotUsedMasternode();
- if (!infoMn.fInfoValid) {
+ if (!dmn) {
LogPrintf("CPrivateSendClientSession::StartNewQueue -- Can't find random masternode!\n");
strAutoDenomResult = _("Can't find random Masternode.");
return false;
}
- privateSendClient.AddUsedMasternode(infoMn.outpoint);
+ privateSendClient.AddUsedMasternode(dmn->collateralOutpoint);
// skip next mn payments winners
- if (mnpayments.IsScheduled(infoMn, 0)) {
- LogPrintf("CPrivateSendClientSession::StartNewQueue -- skipping winner, masternode=%s\n", infoMn.outpoint.ToStringShort());
+ if (mnpayments.IsScheduled(dmn, 0)) {
+ LogPrintf("CPrivateSendClientSession::StartNewQueue -- skipping winner, masternode=%s\n", dmn->proTxHash.ToString());
nTries++;
continue;
}
- if (infoMn.nLastDsq != 0 && infoMn.nLastDsq + nMnCount / 5 > mnodeman.nDsqCount) {
+ int64_t nLastDsq = mmetaman.GetMetaInfo(dmn->proTxHash)->GetLastDsq();
+ if (nLastDsq != 0 && nLastDsq + nMnCount / 5 > mmetaman.GetDsqCount()) {
LogPrintf("CPrivateSendClientSession::StartNewQueue -- Too early to mix on this masternode!"
" masternode=%s addr=%s nLastDsq=%d CountEnabled/5=%d nDsqCount=%d\n",
- infoMn.outpoint.ToStringShort(), infoMn.addr.ToString(), infoMn.nLastDsq,
- nMnCount / 5, mnodeman.nDsqCount);
+ dmn->proTxHash.ToString(), dmn->pdmnState->addr.ToString(), nLastDsq,
+ nMnCount / 5, mmetaman.GetDsqCount());
nTries++;
continue;
}
- if (connman.IsMasternodeOrDisconnectRequested(infoMn.addr)) {
- LogPrintf("CPrivateSendClientSession::StartNewQueue -- skipping masternode connection, addr=%s\n", infoMn.addr.ToString());
+ if (connman.IsMasternodeOrDisconnectRequested(dmn->pdmnState->addr)) {
+ LogPrintf("CPrivateSendClientSession::StartNewQueue -- skipping masternode connection, addr=%s\n", dmn->pdmnState->addr.ToString());
nTries++;
continue;
}
- LogPrintf("CPrivateSendClientSession::StartNewQueue -- attempt %d connection to Masternode %s\n", nTries, infoMn.addr.ToString());
+ LogPrintf("CPrivateSendClientSession::StartNewQueue -- attempt %d connection to Masternode %s\n", nTries, dmn->pdmnState->addr.ToString());
std::vector vecAmounts;
pwalletMain->ConvertList(vecTxIn, vecAmounts);
@@ -1123,14 +1160,14 @@ bool CPrivateSendClientSession::StartNewQueue(CAmount nValueMin, CAmount nBalanc
nSessionDenom = CPrivateSend::GetDenominationsByAmounts(vecAmounts);
}
- infoMixingMasternode = infoMn;
- connman.AddPendingMasternode(infoMn.addr);
- pendingDsaRequest = CPendingDsaRequest(infoMn.addr, CPrivateSendAccept(nSessionDenom, txMyCollateral));
+ mixingMasternode = dmn;
+ connman.AddPendingMasternode(dmn->pdmnState->addr);
+ pendingDsaRequest = CPendingDsaRequest(dmn->pdmnState->addr, CPrivateSendAccept(nSessionDenom, txMyCollateral));
// TODO: add new state POOL_STATE_CONNECTING and bump MIN_PRIVATESEND_PEER_PROTO_VERSION
SetState(POOL_STATE_QUEUE);
nTimeLastSuccessfulStep = GetTime();
LogPrintf("CPrivateSendClientSession::StartNewQueue -- pending connection, nSessionDenom: %d (%s), addr=%s\n",
- nSessionDenom, CPrivateSend::GetDenominationsToString(nSessionDenom), infoMn.addr.ToString());
+ nSessionDenom, CPrivateSend::GetDenominationsToString(nSessionDenom), dmn->pdmnState->addr.ToString());
strAutoDenomResult = _("Trying to connect...");
return true;
}
@@ -1596,9 +1633,9 @@ bool CPrivateSendClientSession::CreateDenominated(const CompactTallyItem& tallyI
void CPrivateSendClientSession::RelayIn(const CPrivateSendEntry& entry, CConnman& connman)
{
- if (!infoMixingMasternode.fInfoValid) return;
+ if (!mixingMasternode) return;
- connman.ForNode(infoMixingMasternode.addr, [&entry, &connman](CNode* pnode) {
+ connman.ForNode(mixingMasternode->pdmnState->addr, [&entry, &connman](CNode* pnode) {
LogPrintf("CPrivateSendClientSession::RelayIn -- found master, relaying message to %s\n", pnode->addr.ToString());
CNetMsgMaker msgMaker(pnode->GetSendVersion());
connman.PushMessage(pnode, msgMaker.Make(NetMsgType::DSVIN, entry));
diff --git a/src/privatesend-client.h b/src/privatesend-client.h
index aec8a97d3db7..3d8ad5fcafcf 100644
--- a/src/privatesend-client.h
+++ b/src/privatesend-client.h
@@ -5,13 +5,15 @@
#ifndef PRIVATESENDCLIENT_H
#define PRIVATESENDCLIENT_H
-#include "masternode.h"
#include "privatesend-util.h"
#include "privatesend.h"
#include "wallet/wallet.h"
+#include "evo/deterministicmns.h"
+
class CPrivateSendClientManager;
class CConnman;
+class CNode;
static const int DENOMS_COUNT_MAX = 100;
@@ -92,7 +94,7 @@ class CPrivateSendClientSession : public CPrivateSendBaseSession
std::string strLastMessage;
std::string strAutoDenomResult;
- masternode_info_t infoMixingMasternode;
+ CDeterministicMNCPtr mixingMasternode;
CMutableTransaction txMyCollateral; // client side collateral
CPendingDsaRequest pendingDsaRequest;
@@ -139,7 +141,7 @@ class CPrivateSendClientSession : public CPrivateSendBaseSession
fLastEntryAccepted(false),
strLastMessage(),
strAutoDenomResult(),
- infoMixingMasternode(),
+ mixingMasternode(),
txMyCollateral(),
pendingDsaRequest(),
keyHolderStorage()
@@ -154,7 +156,7 @@ class CPrivateSendClientSession : public CPrivateSendBaseSession
std::string GetStatus(bool fWaitForBlock);
- bool GetMixingMasternodeInfo(masternode_info_t& mnInfoRet) const;
+ bool GetMixingMasternodeInfo(CDeterministicMNCPtr& ret) const;
/// Passively run mixing in the background according to the configuration in settings
bool DoAutomaticDenominating(CConnman& connman, bool fDryRun = false);
@@ -235,7 +237,7 @@ class CPrivateSendClientManager : public CPrivateSendBaseManager
std::string GetStatuses();
std::string GetSessionDenoms();
- bool GetMixingMasternodesInfo(std::vector& vecMnInfoRet) const;
+ bool GetMixingMasternodesInfo(std::vector& vecDmnsRet) const;
/// Passively run mixing in the background according to the configuration in settings
bool DoAutomaticDenominating(CConnman& connman, bool fDryRun = false);
@@ -245,7 +247,7 @@ class CPrivateSendClientManager : public CPrivateSendBaseManager
void ProcessPendingDsaRequest(CConnman& connman);
void AddUsedMasternode(const COutPoint& outpointMn);
- masternode_info_t GetNotUsedMasternode();
+ CDeterministicMNCPtr GetRandomNotUsedMasternode();
void UpdatedSuccessBlock();
diff --git a/src/privatesend-server.cpp b/src/privatesend-server.cpp
index 57f8267f67ea..ee17fa0af0b4 100644
--- a/src/privatesend-server.cpp
+++ b/src/privatesend-server.cpp
@@ -8,13 +8,14 @@
#include "consensus/validation.h"
#include "core_io.h"
#include "init.h"
+#include "masternode-meta.h"
#include "masternode-sync.h"
-#include "masternodeman.h"
#include "netmessagemaker.h"
#include "script/interpreter.h"
#include "txmempool.h"
#include "util.h"
#include "utilmoneystr.h"
+#include "validation.h"
CPrivateSendServer privateSendServer;
@@ -44,8 +45,9 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, const std::string& strComm
LogPrint("privatesend", "DSACCEPT -- nDenom %d (%s) txCollateral %s", dsa.nDenom, CPrivateSend::GetDenominationsToString(dsa.nDenom), dsa.txCollateral.ToString());
- masternode_info_t mnInfo;
- if (!mnodeman.GetMasternodeInfo(activeMasternodeInfo.outpoint, mnInfo)) {
+ auto mnList = deterministicMNManager->GetListAtChainTip();
+ auto dmn = mnList.GetValidMNByCollateral(activeMasternodeInfo.outpoint);
+ if (!dmn) {
PushStatus(pfrom, STATUS_REJECTED, ERR_MN_LIST, connman);
return;
}
@@ -65,7 +67,8 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, const std::string& strComm
}
}
- if (mnInfo.nLastDsq != 0 && mnInfo.nLastDsq + mnodeman.CountMasternodes() / 5 > mnodeman.nDsqCount) {
+ int64_t nLastDsq = mmetaman.GetMetaInfo(dmn->proTxHash)->GetLastDsq();
+ if (nLastDsq != 0 && nLastDsq + mnList.GetValidMNsCount() / 5 > mmetaman.GetDsqCount()) {
LogPrintf("DSACCEPT -- last dsq too recent, must wait: addr=%s\n", pfrom->addr.ToString());
PushStatus(pfrom, STATUS_REJECTED, ERR_RECENT, connman);
return;
@@ -111,12 +114,12 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, const std::string& strComm
if (dsq.IsExpired()) return;
- masternode_info_t mnInfo;
- if (!mnodeman.GetMasternodeInfo(dsq.masternodeOutpoint, mnInfo)) return;
+ auto mnList = deterministicMNManager->GetListAtChainTip();
+ auto dmn = mnList.GetValidMNByCollateral(dsq.masternodeOutpoint);
+ if (!dmn) return;
- if (!dsq.CheckSignature(mnInfo.legacyKeyIDOperator, mnInfo.blsPubKeyOperator)) {
- // we probably have outdated info
- mnodeman.AskForMN(pfrom, dsq.masternodeOutpoint, connman);
+ if (!dsq.CheckSignature(dmn->pdmnState->pubKeyOperator)) {
+ // TODO ban?
return;
}
@@ -124,21 +127,22 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, const std::string& strComm
for (const auto& q : vecPrivateSendQueue) {
if (q.masternodeOutpoint == dsq.masternodeOutpoint) {
// no way same mn can send another "not yet ready" dsq this soon
- LogPrint("privatesend", "DSQUEUE -- Masternode %s is sending WAY too many dsq messages\n", mnInfo.addr.ToString());
+ LogPrint("privatesend", "DSQUEUE -- Masternode %s is sending WAY too many dsq messages\n", dmn->pdmnState->addr.ToString());
return;
}
}
- int nThreshold = mnInfo.nLastDsq + mnodeman.CountMasternodes() / 5;
- LogPrint("privatesend", "DSQUEUE -- nLastDsq: %d threshold: %d nDsqCount: %d\n", mnInfo.nLastDsq, nThreshold, mnodeman.nDsqCount);
+ int64_t nLastDsq = mmetaman.GetMetaInfo(dmn->proTxHash)->GetLastDsq();
+ int nThreshold = nLastDsq + mnList.GetValidMNsCount() / 5;
+ LogPrint("privatesend", "DSQUEUE -- nLastDsq: %d threshold: %d nDsqCount: %d\n", nLastDsq, nThreshold, mmetaman.GetDsqCount());
//don't allow a few nodes to dominate the queuing process
- if (mnInfo.nLastDsq != 0 && nThreshold > mnodeman.nDsqCount) {
- LogPrint("privatesend", "DSQUEUE -- Masternode %s is sending too many dsq messages\n", mnInfo.addr.ToString());
+ if (nLastDsq != 0 && nThreshold > mmetaman.GetDsqCount()) {
+ LogPrint("privatesend", "DSQUEUE -- Masternode %s is sending too many dsq messages\n", dmn->pdmnState->addr.ToString());
return;
}
- mnodeman.AllowMixing(dsq.masternodeOutpoint);
+ mmetaman.AllowMixing(dmn->proTxHash);
- LogPrint("privatesend", "DSQUEUE -- new PrivateSend queue (%s) from masternode %s\n", dsq.ToString(), mnInfo.addr.ToString());
+ LogPrint("privatesend", "DSQUEUE -- new PrivateSend queue (%s) from masternode %s\n", dsq.ToString(), dmn->pdmnState->addr.ToString());
vecPrivateSendQueue.push_back(dsq);
dsq.Relay(connman);
}
diff --git a/src/privatesend.cpp b/src/privatesend.cpp
index b6189e424813..043bcfa50d20 100644
--- a/src/privatesend.cpp
+++ b/src/privatesend.cpp
@@ -8,13 +8,13 @@
#include "consensus/validation.h"
#include "masternode-payments.h"
#include "masternode-sync.h"
-#include "masternodeman.h"
#include "messagesigner.h"
#include "netmessagemaker.h"
#include "script/sign.h"
#include "txmempool.h"
#include "util.h"
#include "utilmoneystr.h"
+#include "validation.h"
#include
@@ -36,14 +36,7 @@ bool CPrivateSendEntry::AddScriptSig(const CTxIn& txin)
uint256 CPrivateSendQueue::GetSignatureHash() const
{
- // Remove after migration to 70211
- {
- masternode_info_t mnInfo;
- mnodeman.GetMasternodeInfo(masternodeOutpoint, mnInfo);
- return SerializeHash(*this, SER_GETHASH, mnInfo.nProtocolVersion);
- }
- // END remove, replace with the code below
- // return SerializeHash(*this);
+ return SerializeHash(*this);
}
bool CPrivateSendQueue::Sign()
@@ -52,75 +45,26 @@ bool CPrivateSendQueue::Sign()
std::string strError = "";
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
- uint256 hash = GetSignatureHash();
- CBLSSignature sig = activeMasternodeInfo.blsKeyOperator->Sign(hash);
- if (!sig.IsValid()) {
- return false;
- }
- sig.GetBuf(vchSig);
- } else if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
- uint256 hash = GetSignatureHash();
-
- if (!CHashSigner::SignHash(hash, activeMasternodeInfo.legacyKeyOperator, vchSig)) {
- LogPrintf("CPrivateSendQueue::Sign -- SignHash() failed\n");
- return false;
- }
-
- if (!CHashSigner::VerifyHash(hash, activeMasternodeInfo.legacyKeyIDOperator, vchSig, strError)) {
- LogPrintf("CPrivateSendQueue::Sign -- VerifyHash() failed, error: %s\n", strError);
- return false;
- }
- } else {
- std::string strMessage = CTxIn(masternodeOutpoint).ToString() +
- std::to_string(nDenom) +
- std::to_string(nTime) +
- std::to_string(fReady);
-
- if (!CMessageSigner::SignMessage(strMessage, vchSig, activeMasternodeInfo.legacyKeyOperator)) {
- LogPrintf("CPrivateSendQueue::Sign -- SignMessage() failed, %s\n", ToString());
- return false;
- }
-
- if (!CMessageSigner::VerifyMessage(activeMasternodeInfo.legacyKeyIDOperator, vchSig, strMessage, strError)) {
- LogPrintf("CPrivateSendQueue::Sign -- VerifyMessage() failed, error: %s\n", strError);
- return false;
- }
+ uint256 hash = GetSignatureHash();
+ CBLSSignature sig = activeMasternodeInfo.blsKeyOperator->Sign(hash);
+ if (!sig.IsValid()) {
+ return false;
}
+ sig.GetBuf(vchSig);
return true;
}
-bool CPrivateSendQueue::CheckSignature(const CKeyID& keyIDOperator, const CBLSPublicKey& blsPubKey) const
+bool CPrivateSendQueue::CheckSignature(const CBLSPublicKey& blsPubKey) const
{
std::string strError = "";
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
- uint256 hash = GetSignatureHash();
-
- CBLSSignature sig;
- sig.SetBuf(vchSig);
- if (!sig.IsValid() || !sig.VerifyInsecure(blsPubKey, hash)) {
- LogPrintf("CTxLockVote::CheckSignature -- VerifyInsecure() failed\n");
- return false;
- }
- } else if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
- uint256 hash = GetSignatureHash();
+ uint256 hash = GetSignatureHash();
- if (!CHashSigner::VerifyHash(hash, keyIDOperator, vchSig, strError)) {
- // we don't care about queues with old signature format
- LogPrintf("CPrivateSendQueue::CheckSignature -- VerifyHash() failed, error: %s\n", strError);
- return false;
- }
- } else {
- std::string strMessage = CTxIn(masternodeOutpoint).ToString() +
- std::to_string(nDenom) +
- std::to_string(nTime) +
- std::to_string(fReady);
-
- if (!CMessageSigner::VerifyMessage(keyIDOperator, vchSig, strMessage, strError)) {
- LogPrintf("CPrivateSendQueue::CheckSignature -- Got bad Masternode queue signature: %s; error: %s\n", ToString(), strError);
- return false;
- }
+ CBLSSignature sig;
+ sig.SetBuf(vchSig);
+ if (!sig.IsValid() || !sig.VerifyInsecure(blsPubKey, hash)) {
+ LogPrintf("CTxLockVote::CheckSignature -- VerifyInsecure() failed\n");
+ return false;
}
return true;
@@ -147,71 +91,28 @@ bool CPrivateSendBroadcastTx::Sign()
std::string strError = "";
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
- uint256 hash = GetSignatureHash();
+ uint256 hash = GetSignatureHash();
- CBLSSignature sig = activeMasternodeInfo.blsKeyOperator->Sign(hash);
- if (!sig.IsValid()) {
- return false;
- }
- sig.GetBuf(vchSig);
- } else if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
- uint256 hash = GetSignatureHash();
-
- if (!CHashSigner::SignHash(hash, activeMasternodeInfo.legacyKeyOperator, vchSig)) {
- LogPrintf("CPrivateSendBroadcastTx::Sign -- SignHash() failed\n");
- return false;
- }
-
- if (!CHashSigner::VerifyHash(hash, activeMasternodeInfo.legacyKeyIDOperator, vchSig, strError)) {
- LogPrintf("CPrivateSendBroadcastTx::Sign -- VerifyHash() failed, error: %s\n", strError);
- return false;
- }
- } else {
- std::string strMessage = tx->GetHash().ToString() + std::to_string(sigTime);
-
- if (!CMessageSigner::SignMessage(strMessage, vchSig, activeMasternodeInfo.legacyKeyOperator)) {
- LogPrintf("CPrivateSendBroadcastTx::Sign -- SignMessage() failed\n");
- return false;
- }
-
- if (!CMessageSigner::VerifyMessage(activeMasternodeInfo.legacyKeyIDOperator, vchSig, strMessage, strError)) {
- LogPrintf("CPrivateSendBroadcastTx::Sign -- VerifyMessage() failed, error: %s\n", strError);
- return false;
- }
+ CBLSSignature sig = activeMasternodeInfo.blsKeyOperator->Sign(hash);
+ if (!sig.IsValid()) {
+ return false;
}
+ sig.GetBuf(vchSig);
return true;
}
-bool CPrivateSendBroadcastTx::CheckSignature(const CKeyID& keyIDOperator, const CBLSPublicKey& blsPubKey) const
+bool CPrivateSendBroadcastTx::CheckSignature(const CBLSPublicKey& blsPubKey) const
{
std::string strError = "";
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
- uint256 hash = GetSignatureHash();
-
- CBLSSignature sig;
- sig.SetBuf(vchSig);
- if (!sig.IsValid() || !sig.VerifyInsecure(blsPubKey, hash)) {
- LogPrintf("CTxLockVote::CheckSignature -- VerifyInsecure() failed\n");
- return false;
- }
- } else if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
- uint256 hash = GetSignatureHash();
-
- if (!CHashSigner::VerifyHash(hash, keyIDOperator, vchSig, strError)) {
- // we don't care about dstxes with old signature format
- LogPrintf("CPrivateSendBroadcastTx::CheckSignature -- VerifyHash() failed, error: %s\n", strError);
- return false;
- }
- } else {
- std::string strMessage = tx->GetHash().ToString() + std::to_string(sigTime);
+ uint256 hash = GetSignatureHash();
- if (!CMessageSigner::VerifyMessage(keyIDOperator, vchSig, strMessage, strError)) {
- LogPrintf("CPrivateSendBroadcastTx::CheckSignature -- Got bad dstx signature, error: %s\n", strError);
- return false;
- }
+ CBLSSignature sig;
+ sig.SetBuf(vchSig);
+ if (!sig.IsValid() || !sig.VerifyInsecure(blsPubKey, hash)) {
+ LogPrintf("CTxLockVote::CheckSignature -- VerifyInsecure() failed\n");
+ return false;
}
return true;
@@ -572,7 +473,7 @@ void CPrivateSend::CheckDSTXes(int nHeight)
void CPrivateSend::UpdatedBlockTip(const CBlockIndex* pindex)
{
- if (pindex && !fLiteMode && masternodeSync.IsMasternodeListSynced()) {
+ if (pindex && !fLiteMode && masternodeSync.IsBlockchainSynced()) {
CheckDSTXes(pindex->nHeight);
}
}
diff --git a/src/privatesend.h b/src/privatesend.h
index 440da1e7a084..f8e85097e36e 100644
--- a/src/privatesend.h
+++ b/src/privatesend.h
@@ -225,7 +225,7 @@ class CPrivateSendQueue
*/
bool Sign();
/// Check if we have a valid Masternode address
- bool CheckSignature(const CKeyID& keyIDOperator, const CBLSPublicKey& blsPubKey) const;
+ bool CheckSignature(const CBLSPublicKey& blsPubKey) const;
bool Relay(CConnman& connman);
@@ -306,7 +306,7 @@ class CPrivateSendBroadcastTx
uint256 GetSignatureHash() const;
bool Sign();
- bool CheckSignature(const CKeyID& keyIDOperator, const CBLSPublicKey& blsPubKey) const;
+ bool CheckSignature(const CBLSPublicKey& blsPubKey) const;
void SetConfirmedHeight(int nConfirmedHeightIn) { nConfirmedHeight = nConfirmedHeightIn; }
bool IsExpired(int nHeight);
diff --git a/src/protocol.cpp b/src/protocol.cpp
index fa1ccaf9ce77..9a4b661e17c6 100644
--- a/src/protocol.cpp
+++ b/src/protocol.cpp
@@ -44,17 +44,6 @@ const char *TXLOCKREQUEST="ix";
const char *TXLOCKVOTE="txlvote";
const char *SPORK="spork";
const char *GETSPORKS="getsporks";
-const char *MASTERNODEPAYMENTVOTE="mnw";
-const char *MASTERNODEPAYMENTBLOCK="mnwb";
-const char *MASTERNODEPAYMENTSYNC="mnget";
-const char *MNBUDGETSYNC="mnvs"; // deprecated since 12.1
-const char *MNBUDGETVOTE="mvote"; // deprecated since 12.1
-const char *MNBUDGETPROPOSAL="mprop"; // deprecated since 12.1
-const char *MNBUDGETFINAL="fbs"; // deprecated since 12.1
-const char *MNBUDGETFINALVOTE="fbvote"; // deprecated since 12.1
-const char *MNQUORUM="mn quorum"; // not implemented
-const char *MNANNOUNCE="mnb";
-const char *MNPING="mnp";
const char *DSACCEPT="dsa";
const char *DSVIN="dsi";
const char *DSFINALTX="dsf";
@@ -63,12 +52,10 @@ const char *DSCOMPLETE="dsc";
const char *DSSTATUSUPDATE="dssu";
const char *DSTX="dstx";
const char *DSQUEUE="dsq";
-const char *DSEG="dseg";
const char *SYNCSTATUSCOUNT="ssc";
const char *MNGOVERNANCESYNC="govsync";
const char *MNGOVERNANCEOBJECT="govobj";
const char *MNGOVERNANCEOBJECTVOTE="govobjvote";
-const char *MNVERIFY="mnv";
const char *GETMNLISTDIFF="getmnlistd";
const char *MNLISTDIFF="mnlistdiff";
const char *QFCOMMITMENT="qfcommit";
@@ -87,19 +74,19 @@ static const char* ppszTypeName[] =
NetMsgType::TXLOCKREQUEST,
NetMsgType::TXLOCKVOTE,
NetMsgType::SPORK,
- NetMsgType::MASTERNODEPAYMENTVOTE,
- NetMsgType::MASTERNODEPAYMENTBLOCK, // reusing, was MNSCANERROR previousely, was NOT used in 12.0, we need this for inv
- NetMsgType::MNBUDGETVOTE, // deprecated since 12.1
- NetMsgType::MNBUDGETPROPOSAL, // deprecated since 12.1
- NetMsgType::MNBUDGETFINAL, // deprecated since 12.1
- NetMsgType::MNBUDGETFINALVOTE, // deprecated since 12.1
- NetMsgType::MNQUORUM, // not implemented
- NetMsgType::MNANNOUNCE,
- NetMsgType::MNPING,
+ "unused inv type 7",
+ "unused inv type 8",
+ "unused inv type 9",
+ "unused inv type 10",
+ "unused inv type 11",
+ "unused inv type 12",
+ "unused inv type 13",
+ "unused inv type 14",
+ "unused inv type 15",
NetMsgType::DSTX,
NetMsgType::MNGOVERNANCEOBJECT,
NetMsgType::MNGOVERNANCEOBJECTVOTE,
- NetMsgType::MNVERIFY,
+ "unused inv type 19",
"compact block", // Should never occur
NetMsgType::QFCOMMITMENT,
NetMsgType::QDCOMMITMENT,
@@ -142,11 +129,6 @@ const static std::string allNetMessageTypes[] = {
NetMsgType::TXLOCKVOTE,
NetMsgType::SPORK,
NetMsgType::GETSPORKS,
- NetMsgType::MASTERNODEPAYMENTVOTE,
- // NetMsgType::MASTERNODEPAYMENTBLOCK, // there is no message for this, only inventory
- NetMsgType::MASTERNODEPAYMENTSYNC,
- NetMsgType::MNANNOUNCE,
- NetMsgType::MNPING,
NetMsgType::DSACCEPT,
NetMsgType::DSVIN,
NetMsgType::DSFINALTX,
@@ -155,12 +137,10 @@ const static std::string allNetMessageTypes[] = {
NetMsgType::DSSTATUSUPDATE,
NetMsgType::DSTX,
NetMsgType::DSQUEUE,
- NetMsgType::DSEG,
NetMsgType::SYNCSTATUSCOUNT,
NetMsgType::MNGOVERNANCESYNC,
NetMsgType::MNGOVERNANCEOBJECT,
NetMsgType::MNGOVERNANCEOBJECTVOTE,
- NetMsgType::MNVERIFY,
NetMsgType::GETMNLISTDIFF,
NetMsgType::MNLISTDIFF,
NetMsgType::QFCOMMITMENT,
diff --git a/src/protocol.h b/src/protocol.h
index ba1b25c45675..2d2e85e84087 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -250,10 +250,6 @@ extern const char *TXLOCKREQUEST;
extern const char *TXLOCKVOTE;
extern const char *SPORK;
extern const char *GETSPORKS;
-extern const char *MASTERNODEPAYMENTVOTE;
-extern const char *MASTERNODEPAYMENTSYNC;
-extern const char *MNANNOUNCE;
-extern const char *MNPING;
extern const char *DSACCEPT;
extern const char *DSVIN;
extern const char *DSFINALTX;
@@ -262,12 +258,10 @@ extern const char *DSCOMPLETE;
extern const char *DSSTATUSUPDATE;
extern const char *DSTX;
extern const char *DSQUEUE;
-extern const char *DSEG;
extern const char *SYNCSTATUSCOUNT;
extern const char *MNGOVERNANCESYNC;
extern const char *MNGOVERNANCEOBJECT;
extern const char *MNGOVERNANCEOBJECTVOTE;
-extern const char *MNVERIFY;
extern const char *GETMNLISTDIFF;
extern const char *MNLISTDIFF;
extern const char *QFCOMMITMENT;
@@ -358,19 +352,11 @@ enum GetDataMsg {
MSG_TXLOCK_REQUEST = 4,
MSG_TXLOCK_VOTE = 5,
MSG_SPORK = 6,
- MSG_MASTERNODE_PAYMENT_VOTE = 7,
- MSG_MASTERNODE_PAYMENT_BLOCK = 8, // reusing, was MSG_MASTERNODE_SCANNING_ERROR previousely, was NOT used in 12.0
- MSG_BUDGET_VOTE = 9, // deprecated since 12.1
- MSG_BUDGET_PROPOSAL = 10, // deprecated since 12.1
- MSG_BUDGET_FINALIZED = 11, // deprecated since 12.1
- MSG_BUDGET_FINALIZED_VOTE = 12, // deprecated since 12.1
- MSG_MASTERNODE_QUORUM = 13, // not implemented
- MSG_MASTERNODE_ANNOUNCE = 14,
- MSG_MASTERNODE_PING = 15,
+ /* 7 - 15 were used in old Dash versions and were mainly budget and MN broadcast/ping related*/
MSG_DSTX = 16,
MSG_GOVERNANCE_OBJECT = 17,
MSG_GOVERNANCE_OBJECT_VOTE = 18,
- MSG_MASTERNODE_VERIFY = 19,
+ /* 19 was used for MSG_MASTERNODE_VERIFY and is not supported anymore */
// Nodes may always request a MSG_CMPCT_BLOCK in a getdata, however,
// MSG_CMPCT_BLOCK should not appear in any invs except as a part of getdata.
MSG_CMPCT_BLOCK = 20, //!< Defined in BIP152
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index eff7235187d9..2803c05429ee 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -419,8 +419,6 @@ void BitcoinGUI::createActions()
openRepairAction->setStatusTip(tr("Show wallet repair options"));
openConfEditorAction = new QAction(QIcon(":/icons/" + theme + "/edit"), tr("Open Wallet &Configuration File"), this);
openConfEditorAction->setStatusTip(tr("Open configuration file"));
- openMNConfEditorAction = new QAction(QIcon(":/icons/" + theme + "/edit"), tr("Open &Masternode Configuration File"), this);
- openMNConfEditorAction->setStatusTip(tr("Open Masternode configuration file"));
showBackupsAction = new QAction(QIcon(":/icons/" + theme + "/browse"), tr("Show Automatic &Backups"), this);
showBackupsAction->setStatusTip(tr("Show automatically created wallet backups"));
// initially disable the debug window menu items
@@ -463,7 +461,6 @@ void BitcoinGUI::createActions()
// Open configs and backup folder from menu
connect(openConfEditorAction, SIGNAL(triggered()), this, SLOT(showConfEditor()));
- connect(openMNConfEditorAction, SIGNAL(triggered()), this, SLOT(showMNConfEditor()));
connect(showBackupsAction, SIGNAL(triggered()), this, SLOT(showBackups()));
// Get restart command-line parameters and handle restart
@@ -541,7 +538,6 @@ void BitcoinGUI::createMenuBar()
tools->addAction(openRepairAction);
tools->addSeparator();
tools->addAction(openConfEditorAction);
- tools->addAction(openMNConfEditorAction);
tools->addAction(showBackupsAction);
}
@@ -756,7 +752,6 @@ void BitcoinGUI::createIconMenu(QMenu *pmenu)
pmenu->addAction(openRepairAction);
pmenu->addSeparator();
pmenu->addAction(openConfEditorAction);
- pmenu->addAction(openMNConfEditorAction);
pmenu->addAction(showBackupsAction);
#ifndef Q_OS_MAC // This is built-in on Mac
pmenu->addSeparator();
@@ -837,11 +832,6 @@ void BitcoinGUI::showConfEditor()
GUIUtil::openConfigfile();
}
-void BitcoinGUI::showMNConfEditor()
-{
- GUIUtil::openMNConfigfile();
-}
-
void BitcoinGUI::showBackups()
{
GUIUtil::showBackups();
diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h
index e03648b95103..f1e21f26f42f 100644
--- a/src/qt/bitcoingui.h
+++ b/src/qt/bitcoingui.h
@@ -121,7 +121,6 @@ class BitcoinGUI : public QMainWindow
QAction *openPeersAction;
QAction *openRepairAction;
QAction *openConfEditorAction;
- QAction *openMNConfEditorAction;
QAction *showBackupsAction;
QAction *openAction;
QAction *showHelpMessageAction;
@@ -248,8 +247,6 @@ private Q_SLOTS:
/** Open external (default) editor with dash.conf */
void showConfEditor();
- /** Open external (default) editor with masternode.conf */
- void showMNConfEditor();
/** Show folder with wallet backups in default file browser */
void showBackups();
diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp
index 07ff4ddcbb7a..98d8f94d7093 100644
--- a/src/qt/clientmodel.cpp
+++ b/src/qt/clientmodel.cpp
@@ -20,10 +20,11 @@
#include "ui_interface.h"
#include "util.h"
-#include "masternodeman.h"
#include "masternode-sync.h"
#include "privatesend.h"
+#include "evo/deterministicmns.h"
+
#include
#include
@@ -83,10 +84,10 @@ int ClientModel::getNumConnections(unsigned int flags) const
QString ClientModel::getMasternodeCountString() const
{
// return tr("Total: %1 (PS compatible: %2 / Enabled: %3) (IPv4: %4, IPv6: %5, TOR: %6)").arg(QString::number((int)mnodeman.size()))
- return tr("Total: %1 (PS compatible: %2 / Enabled: %3)")
- .arg(QString::number((int)mnodeman.CountMasternodes(0)))
- .arg(QString::number((int)mnodeman.CountEnabled(MIN_PRIVATESEND_PEER_PROTO_VERSION)))
- .arg(QString::number((int)mnodeman.CountEnabled()));
+ auto mnList = deterministicMNManager->GetListAtChainTip();
+ return tr("Total: %1 (Enabled: %2)")
+ .arg(QString::number((int)mnList.GetAllMNsCount()))
+ .arg(QString::number((int)mnList.GetValidMNsCount()));
// .arg(QString::number((int)mnodeman.CountByIP(NET_IPV4)))
// .arg(QString::number((int)mnodeman.CountByIP(NET_IPV6)))
// .arg(QString::number((int)mnodeman.CountByIP(NET_TOR)));
diff --git a/src/qt/dash.cpp b/src/qt/dash.cpp
index 5b08ca36e33a..d588b3724c9f 100644
--- a/src/qt/dash.cpp
+++ b/src/qt/dash.cpp
@@ -26,7 +26,6 @@
#include "paymentserver.h"
#include "walletmodel.h"
#endif
-#include "masternodeconfig.h"
#include "init.h"
#include "rpc/server.h"
@@ -684,14 +683,6 @@ int main(int argc, char *argv[])
initTranslations(qtTranslatorBase, qtTranslator, translatorBase, translator);
#ifdef ENABLE_WALLET
- /// 7a. parse masternode.conf
- std::string strErr;
- if(!masternodeConfig.read(strErr)) {
- QMessageBox::critical(0, QObject::tr("Dash Core"),
- QObject::tr("Error reading masternode configuration file: %1").arg(strErr.c_str()));
- return EXIT_FAILURE;
- }
-
/// 8. URI IPC sending
// - Do this early as we don't want to bother initializing if we are just calling IPC
// - Do this *after* setting up the data directory, as the data directory hash is used in the name
diff --git a/src/qt/dashstrings.cpp b/src/qt/dashstrings.cpp
index 7fe00c06893d..c15290bacd6f 100644
--- a/src/qt/dashstrings.cpp
+++ b/src/qt/dashstrings.cpp
@@ -367,7 +367,6 @@ QT_TRANSLATE_NOOP("dash-core", "Connect to a node to retrieve peer addresses, an
QT_TRANSLATE_NOOP("dash-core", "Connection options:"),
QT_TRANSLATE_NOOP("dash-core", "Copyright (C)"),
QT_TRANSLATE_NOOP("dash-core", "Corrupted block database detected"),
-QT_TRANSLATE_NOOP("dash-core", "Could not parse masternode.conf"),
QT_TRANSLATE_NOOP("dash-core", "Debugging/Testing options:"),
QT_TRANSLATE_NOOP("dash-core", "Do not load the wallet and disable wallet RPC calls"),
QT_TRANSLATE_NOOP("dash-core", "Do you want to rebuild the block database now?"),
@@ -434,7 +433,6 @@ QT_TRANSLATE_NOOP("dash-core", "Invalid amount for -paytxfee=: '%s' (mus
QT_TRANSLATE_NOOP("dash-core", "Invalid input count."),
QT_TRANSLATE_NOOP("dash-core", "Invalid masternodeprivkey. Please see documenation."),
QT_TRANSLATE_NOOP("dash-core", "Invalid netmask specified in -whitelist: '%s'"),
-QT_TRANSLATE_NOOP("dash-core", "Invalid port detected in masternode.conf"),
QT_TRANSLATE_NOOP("dash-core", "Invalid script detected."),
QT_TRANSLATE_NOOP("dash-core", "Invalid spork address specified with -sporkaddr"),
QT_TRANSLATE_NOOP("dash-core", "KeePassHttp id for the established association"),
diff --git a/src/qt/forms/masternodelist.ui b/src/qt/forms/masternodelist.ui
index f479a608d9e7..03c08266d67a 100644
--- a/src/qt/forms/masternodelist.ui
+++ b/src/qt/forms/masternodelist.ui
@@ -49,295 +49,12 @@
0
-
-
- My Masternodes
-
-
- -
-
-
- 0
-
-
-
-
-
- 0
-
-
-
-
-
- Note: Status of your masternodes in local wallet can potentially be slightly incorrect.<br />Always wait for wallet to sync additional data and then double check from another node<br />if your masternode should be running but you still do not see "ENABLED" in "Status" field.
-
-
-
-
-
- -
-
-
-
- 695
- 0
-
-
-
- QAbstractItemView::NoEditTriggers
-
-
- true
-
-
- QAbstractItemView::SingleSelection
-
-
- QAbstractItemView::SelectRows
-
-
- true
-
-
- true
-
-
-
- Alias
-
-
-
-
- Address
-
-
-
-
- Protocol
-
-
-
-
- Status
-
-
-
-
- Active
-
-
-
-
- Last Seen
-
-
-
-
- Payee
-
-
-
-
- -
-
-
- 0
-
-
-
-
-
- S&tart alias
-
-
-
- -
-
-
- Start &all
-
-
-
- -
-
-
- Start &MISSING
-
-
-
- -
-
-
- &Update status
-
-
-
- -
-
-
- Show additional Masternode information
-
-
- Show &Info...
-
-
-
- -
-
-
- Status will be updated automatically in (sec):
-
-
-
- -
-
-
- 0
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
-
-
-
-
-
-
-
- All Masternodes
-
-
- -
-
-
- 0
-
-
-
-
-
- Filter List:
-
-
-
- -
-
-
- Filter masternode list
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 10
- 20
-
-
-
-
- -
-
-
- Node Count:
-
-
-
- -
-
-
- 0
-
-
-
-
-
- -
-
-
- QAbstractItemView::NoEditTriggers
-
-
- true
-
-
- QAbstractItemView::SelectRows
-
-
- QAbstractItemView::NoSelection
-
-
- true
-
-
- true
-
-
-
- Address
-
-
-
-
- Protocol
-
-
-
-
- Status
-
-
-
-
- Active
-
-
-
-
- Last Seen
-
-
-
-
- Payee
-
-
-
-
- -
-
-
- <html><head/><body><p>Note: This list represents the legacy and non-deterministic masternode list. It is only active as long as DIP3 has not been fully activated. After SPORK15 activation, this list will be empty.</p></body></html>
-
-
- Qt::AutoText
-
-
- true
-
-
-
-
-
DIP3 Masternodes
- -
+
-
0
@@ -385,7 +102,7 @@
- -
+
-
QAbstractItemView::NoEditTriggers
@@ -447,19 +164,6 @@
- -
-
-
- <html><head/><body><p>Note: This list is not active yet and only for informational purposes. The network is still running in compatibility mode, which means that the non-deterministic masternode list is still active. Only after SPORK15 activation, this list will become the active one. Also, the values in the payment related fields are not used at the moment, but still updated for every block. Please ignore this until SPORK15 activation.</p></body></html>
-
-
- Qt::AutoText
-
-
- true
-
-
-
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index 0486f121fc9a..31aab8ff2de3 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -447,15 +447,6 @@ void openConfigfile()
QDesktopServices::openUrl(QUrl::fromLocalFile(boostPathToQString(pathConfig)));
}
-void openMNConfigfile()
-{
- boost::filesystem::path pathConfig = GetMasternodeConfigFile();
-
- /* Open masternode.conf with the associated application */
- if (boost::filesystem::exists(pathConfig))
- QDesktopServices::openUrl(QUrl::fromLocalFile(boostPathToQString(pathConfig)));
-}
-
void showBackups()
{
boost::filesystem::path backupsDir = GetBackupsDir();
diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h
index c69b1ad251ce..9360d8e85fb3 100644
--- a/src/qt/guiutil.h
+++ b/src/qt/guiutil.h
@@ -117,9 +117,6 @@ namespace GUIUtil
// Open dash.conf
void openConfigfile();
- // Open masternode.conf
- void openMNConfigfile();
-
// Browse backup folder
void showBackups();
diff --git a/src/qt/masternodelist.cpp b/src/qt/masternodelist.cpp
index ca76e4c5eb52..7552c3cdb5db 100644
--- a/src/qt/masternodelist.cpp
+++ b/src/qt/masternodelist.cpp
@@ -7,8 +7,6 @@
#include "guiutil.h"
#include "init.h"
#include "masternode-sync.h"
-#include "masternodeconfig.h"
-#include "masternodeman.h"
#include "netbase.h"
#include "qrdialog.h"
#include "sync.h"
@@ -40,15 +38,8 @@ MasternodeList::MasternodeList(const PlatformStyle* platformStyle, QWidget* pare
{
ui->setupUi(this);
- ui->startButton->setEnabled(false);
-
- int columnAliasWidth = 100;
int columnAddressWidth = 200;
- int columnProtocolWidth = 60;
int columnStatusWidth = 80;
- int columnActiveWidth = 130;
- int columnLastSeenWidth = 130;
-
int columnPoSeScoreWidth = 80;
int columnRegisteredWidth = 80;
int columnLastPaidWidth = 80;
@@ -56,19 +47,6 @@ MasternodeList::MasternodeList(const PlatformStyle* platformStyle, QWidget* pare
int columnPayeeWidth = 130;
int columnOperatorRewardWidth = 130;
- ui->tableWidgetMyMasternodes->setColumnWidth(0, columnAliasWidth);
- ui->tableWidgetMyMasternodes->setColumnWidth(1, columnAddressWidth);
- ui->tableWidgetMyMasternodes->setColumnWidth(2, columnProtocolWidth);
- ui->tableWidgetMyMasternodes->setColumnWidth(3, columnStatusWidth);
- ui->tableWidgetMyMasternodes->setColumnWidth(4, columnActiveWidth);
- ui->tableWidgetMyMasternodes->setColumnWidth(5, columnLastSeenWidth);
-
- ui->tableWidgetMasternodes->setColumnWidth(0, columnAddressWidth);
- ui->tableWidgetMasternodes->setColumnWidth(1, columnProtocolWidth);
- ui->tableWidgetMasternodes->setColumnWidth(2, columnStatusWidth);
- ui->tableWidgetMasternodes->setColumnWidth(3, columnActiveWidth);
- ui->tableWidgetMasternodes->setColumnWidth(4, columnLastSeenWidth);
-
ui->tableWidgetMasternodesDIP3->setColumnWidth(0, columnAddressWidth);
ui->tableWidgetMasternodesDIP3->setColumnWidth(1, columnStatusWidth);
ui->tableWidgetMasternodesDIP3->setColumnWidth(2, columnPoSeScoreWidth);
@@ -83,16 +61,6 @@ MasternodeList::MasternodeList(const PlatformStyle* platformStyle, QWidget* pare
ui->tableWidgetMasternodesDIP3->insertColumn(8);
ui->tableWidgetMasternodesDIP3->setColumnHidden(8, true);
- ui->tableWidgetMyMasternodes->setContextMenuPolicy(Qt::CustomContextMenu);
- ui->tableWidgetMasternodesDIP3->setContextMenuPolicy(Qt::CustomContextMenu);
-
- QAction* startAliasAction = new QAction(tr("Start alias"), this);
- contextMenu = new QMenu();
- contextMenu->addAction(startAliasAction);
- connect(ui->tableWidgetMyMasternodes, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showContextMenu(const QPoint&)));
- connect(ui->tableWidgetMyMasternodes, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(on_QRButton_clicked()));
- connect(startAliasAction, SIGNAL(triggered()), this, SLOT(on_startButton_clicked()));
-
QAction* copyProTxHashAction = new QAction(tr("Copy ProTx Hash"), this);
QAction* copyCollateralOutpointAction = new QAction(tr("Copy Collateral Outpoint"), this);
contextMenuDIP3 = new QMenu();
@@ -104,16 +72,11 @@ MasternodeList::MasternodeList(const PlatformStyle* platformStyle, QWidget* pare
connect(copyCollateralOutpointAction, SIGNAL(triggered()), this, SLOT(copyCollateralOutpoint_clicked()));
timer = new QTimer(this);
- connect(timer, SIGNAL(timeout()), this, SLOT(updateNodeList()));
- connect(timer, SIGNAL(timeout()), this, SLOT(updateMyNodeList()));
connect(timer, SIGNAL(timeout()), this, SLOT(updateDIP3List()));
timer->start(1000);
- fFilterUpdated = false;
fFilterUpdatedDIP3 = false;
- nTimeFilterUpdated = GetTime();
nTimeFilterUpdatedDIP3 = GetTime();
- updateNodeList();
updateDIP3List();
}
@@ -136,256 +99,12 @@ void MasternodeList::setWalletModel(WalletModel* model)
this->walletModel = model;
}
-void MasternodeList::showContextMenu(const QPoint& point)
-{
- QTableWidgetItem* item = ui->tableWidgetMyMasternodes->itemAt(point);
- if (item) contextMenu->exec(QCursor::pos());
-}
-
void MasternodeList::showContextMenuDIP3(const QPoint& point)
{
QTableWidgetItem* item = ui->tableWidgetMasternodesDIP3->itemAt(point);
if (item) contextMenuDIP3->exec(QCursor::pos());
}
-void MasternodeList::StartAlias(std::string strAlias)
-{
- std::string strStatusHtml;
- strStatusHtml += "Alias: " + strAlias;
-
- for (const auto& mne : masternodeConfig.getEntries()) {
- if (mne.getAlias() == strAlias) {
- std::string strError;
- CMasternodeBroadcast mnb;
-
- bool fSuccess = CMasternodeBroadcast::Create(mne.getIp(), mne.getPrivKey(), mne.getTxHash(), mne.getOutputIndex(), strError, mnb);
-
- int nDoS;
- if (fSuccess && !mnodeman.CheckMnbAndUpdateMasternodeList(NULL, mnb, nDoS, *g_connman)) {
- strError = "Failed to verify MNB";
- fSuccess = false;
- }
-
- if (fSuccess) {
- strStatusHtml += "
Successfully started masternode.";
- mnodeman.NotifyMasternodeUpdates(*g_connman);
- } else {
- strStatusHtml += "
Failed to start masternode.
Error: " + strError;
- }
- break;
- }
- }
- strStatusHtml += "";
-
- QMessageBox msg;
- msg.setText(QString::fromStdString(strStatusHtml));
- msg.exec();
-
- updateMyNodeList(true);
-}
-
-void MasternodeList::StartAll(std::string strCommand)
-{
- int nCountSuccessful = 0;
- int nCountFailed = 0;
- std::string strFailedHtml;
-
- for (const auto& mne : masternodeConfig.getEntries()) {
- std::string strError;
- CMasternodeBroadcast mnb;
-
- int32_t nOutputIndex = 0;
- if (!ParseInt32(mne.getOutputIndex(), &nOutputIndex)) {
- continue;
- }
-
- COutPoint outpoint = COutPoint(uint256S(mne.getTxHash()), nOutputIndex);
-
- if (strCommand == "start-missing" && mnodeman.Has(outpoint)) continue;
-
- bool fSuccess = CMasternodeBroadcast::Create(mne.getIp(), mne.getPrivKey(), mne.getTxHash(), mne.getOutputIndex(), strError, mnb);
-
- int nDoS;
- if (fSuccess && !mnodeman.CheckMnbAndUpdateMasternodeList(NULL, mnb, nDoS, *g_connman)) {
- strError = "Failed to verify MNB";
- fSuccess = false;
- }
-
- if (fSuccess) {
- nCountSuccessful++;
- mnodeman.NotifyMasternodeUpdates(*g_connman);
- } else {
- nCountFailed++;
- strFailedHtml += "\nFailed to start " + mne.getAlias() + ". Error: " + strError;
- }
- }
-
- std::string returnObj;
- returnObj = strprintf("Successfully started %d masternodes, failed to start %d, total %d", nCountSuccessful, nCountFailed, nCountFailed + nCountSuccessful);
- if (nCountFailed > 0) {
- returnObj += strFailedHtml;
- }
-
- QMessageBox msg;
- msg.setText(QString::fromStdString(returnObj));
- msg.exec();
-
- updateMyNodeList(true);
-}
-
-void MasternodeList::updateMyMasternodeInfo(QString strAlias, QString strAddr, const COutPoint& outpoint)
-{
- bool fOldRowFound = false;
- int nNewRow = 0;
-
- for (int i = 0; i < ui->tableWidgetMyMasternodes->rowCount(); i++) {
- if (ui->tableWidgetMyMasternodes->item(i, 0)->text() == strAlias) {
- fOldRowFound = true;
- nNewRow = i;
- break;
- }
- }
-
- if (nNewRow == 0 && !fOldRowFound) {
- nNewRow = ui->tableWidgetMyMasternodes->rowCount();
- ui->tableWidgetMyMasternodes->insertRow(nNewRow);
- }
-
- masternode_info_t infoMn;
- bool fFound = mnodeman.GetMasternodeInfo(outpoint, infoMn);
-
- QTableWidgetItem* aliasItem = new QTableWidgetItem(strAlias);
- QTableWidgetItem* addrItem = new QTableWidgetItem(fFound ? QString::fromStdString(infoMn.addr.ToString()) : strAddr);
- QTableWidgetItem* protocolItem = new QTableWidgetItem(QString::number(fFound ? infoMn.nProtocolVersion : -1));
- QTableWidgetItem* statusItem = new QTableWidgetItem(QString::fromStdString(fFound ? CMasternode::StateToString(infoMn.nActiveState) : "MISSING"));
- QTableWidgetItem* activeSecondsItem = new QTableWidgetItem(QString::fromStdString(DurationToDHMS(fFound ? (infoMn.nTimeLastPing - infoMn.sigTime) : 0)));
- QTableWidgetItem* lastSeenItem = new QTableWidgetItem(QString::fromStdString(DateTimeStrFormat("%Y-%m-%d %H:%M",
- fFound ? infoMn.nTimeLastPing + GetOffsetFromUtc() : 0)));
- QTableWidgetItem* pubkeyItem = new QTableWidgetItem(QString::fromStdString(fFound ? CBitcoinAddress(infoMn.keyIDCollateralAddress).ToString() : ""));
-
- ui->tableWidgetMyMasternodes->setItem(nNewRow, 0, aliasItem);
- ui->tableWidgetMyMasternodes->setItem(nNewRow, 1, addrItem);
- ui->tableWidgetMyMasternodes->setItem(nNewRow, 2, protocolItem);
- ui->tableWidgetMyMasternodes->setItem(nNewRow, 3, statusItem);
- ui->tableWidgetMyMasternodes->setItem(nNewRow, 4, activeSecondsItem);
- ui->tableWidgetMyMasternodes->setItem(nNewRow, 5, lastSeenItem);
- ui->tableWidgetMyMasternodes->setItem(nNewRow, 6, pubkeyItem);
-}
-
-void MasternodeList::updateMyNodeList(bool fForce)
-{
- if (ShutdownRequested()) {
- return;
- }
-
- TRY_LOCK(cs_mymnlist, fLockAcquired);
- if (!fLockAcquired) return;
-
- static int64_t nTimeMyListUpdated = 0;
-
- // automatically update my masternode list only once in MY_MASTERNODELIST_UPDATE_SECONDS seconds,
- // this update still can be triggered manually at any time via button click
- int64_t nSecondsTillUpdate = nTimeMyListUpdated + MY_MASTERNODELIST_UPDATE_SECONDS - GetTime();
- ui->secondsLabel->setText(QString::number(nSecondsTillUpdate));
-
- if (nSecondsTillUpdate > 0 && !fForce) return;
- nTimeMyListUpdated = GetTime();
-
- // Find selected row
- QItemSelectionModel* selectionModel = ui->tableWidgetMyMasternodes->selectionModel();
- QModelIndexList selected = selectionModel->selectedRows();
- int nSelectedRow = selected.count() ? selected.at(0).row() : 0;
-
- ui->tableWidgetMyMasternodes->setSortingEnabled(false);
- for (const auto& mne : masternodeConfig.getEntries()) {
- int32_t nOutputIndex = 0;
- if (!ParseInt32(mne.getOutputIndex(), &nOutputIndex)) {
- continue;
- }
-
- updateMyMasternodeInfo(QString::fromStdString(mne.getAlias()), QString::fromStdString(mne.getIp()), COutPoint(uint256S(mne.getTxHash()), nOutputIndex));
- }
- ui->tableWidgetMyMasternodes->selectRow(nSelectedRow);
- ui->tableWidgetMyMasternodes->setSortingEnabled(true);
-
- // reset "timer"
- ui->secondsLabel->setText("0");
-}
-
-void MasternodeList::updateNodeList()
-{
- if (ShutdownRequested()) {
- return;
- }
-
- TRY_LOCK(cs_mnlist, fLockAcquired);
- if (!fLockAcquired) return;
-
- static int64_t nTimeListUpdated = GetTime();
-
- // to prevent high cpu usage update only once in MASTERNODELIST_UPDATE_SECONDS seconds
- // or MASTERNODELIST_FILTER_COOLDOWN_SECONDS seconds after filter was last changed
- int64_t nSecondsToWait = fFilterUpdated
- ? nTimeFilterUpdated - GetTime() + MASTERNODELIST_FILTER_COOLDOWN_SECONDS
- : nTimeListUpdated - GetTime() + MASTERNODELIST_UPDATE_SECONDS;
-
- if (fFilterUpdated) {
- ui->countLabel->setText(QString::fromStdString(strprintf("Please wait... %d", nSecondsToWait)));
- }
- if (nSecondsToWait > 0) return;
-
- nTimeListUpdated = GetTime();
- fFilterUpdated = false;
-
- QString strToFilter;
- ui->countLabel->setText("Updating...");
- ui->tableWidgetMasternodes->setSortingEnabled(false);
- ui->tableWidgetMasternodes->clearContents();
- ui->tableWidgetMasternodes->setRowCount(0);
-
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
- ui->countLabel->setText(QString::number(0));
- return;
- }
-
- int offsetFromUtc = GetOffsetFromUtc();
-
- std::map mapMasternodes = mnodeman.GetFullMasternodeMap();
-
- for (const auto& mnpair : mapMasternodes) {
- CMasternode mn = mnpair.second;
- // populate list
- // Address, Protocol, Status, Active Seconds, Last Seen, Pub Key
- QTableWidgetItem* addressItem = new QTableWidgetItem(QString::fromStdString(mn.addr.ToString()));
- QTableWidgetItem* protocolItem = new QTableWidgetItem(QString::number(mn.nProtocolVersion));
- QTableWidgetItem* statusItem = new QTableWidgetItem(QString::fromStdString(mn.GetStatus()));
- QTableWidgetItem* activeSecondsItem = new QTableWidgetItem(QString::fromStdString(DurationToDHMS(mn.lastPing.sigTime - mn.sigTime)));
- QTableWidgetItem* lastSeenItem = new QTableWidgetItem(QString::fromStdString(DateTimeStrFormat("%Y-%m-%d %H:%M", mn.lastPing.sigTime + offsetFromUtc)));
- QTableWidgetItem* pubkeyItem = new QTableWidgetItem(QString::fromStdString(CBitcoinAddress(mn.keyIDCollateralAddress).ToString()));
-
- if (strCurrentFilter != "") {
- strToFilter = addressItem->text() + " " +
- protocolItem->text() + " " +
- statusItem->text() + " " +
- activeSecondsItem->text() + " " +
- lastSeenItem->text() + " " +
- pubkeyItem->text();
- if (!strToFilter.contains(strCurrentFilter)) continue;
- }
-
- ui->tableWidgetMasternodes->insertRow(0);
- ui->tableWidgetMasternodes->setItem(0, 0, addressItem);
- ui->tableWidgetMasternodes->setItem(0, 1, protocolItem);
- ui->tableWidgetMasternodes->setItem(0, 2, statusItem);
- ui->tableWidgetMasternodes->setItem(0, 3, activeSecondsItem);
- ui->tableWidgetMasternodes->setItem(0, 4, lastSeenItem);
- ui->tableWidgetMasternodes->setItem(0, 5, pubkeyItem);
- }
-
- ui->countLabel->setText(QString::number(ui->tableWidgetMasternodes->rowCount()));
- ui->tableWidgetMasternodes->setSortingEnabled(true);
-}
-
void MasternodeList::updateDIP3List()
{
if (ShutdownRequested()) {
@@ -404,7 +123,7 @@ void MasternodeList::updateDIP3List()
: nTimeListUpdated - GetTime() + MASTERNODELIST_UPDATE_SECONDS;
if (fFilterUpdatedDIP3) {
- ui->countLabel->setText(QString::fromStdString(strprintf("Please wait... %d", nSecondsToWait)));
+ ui->countLabelDIP3->setText(QString::fromStdString(strprintf("Please wait... %d", nSecondsToWait)));
}
if (nSecondsToWait > 0) return;
@@ -417,10 +136,6 @@ void MasternodeList::updateDIP3List()
ui->tableWidgetMasternodesDIP3->clearContents();
ui->tableWidgetMasternodesDIP3->setRowCount(0);
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
- ui->dip3NoteLabel->setVisible(false);
- }
-
auto mnList = deterministicMNManager->GetListAtChainTip();
auto projectedPayees = mnList.GetProjectedMNPayees(mnList.GetValidMNsCount());
std::map nextPayments;
@@ -497,14 +212,6 @@ void MasternodeList::updateDIP3List()
ui->tableWidgetMasternodesDIP3->setSortingEnabled(true);
}
-void MasternodeList::on_filterLineEdit_textChanged(const QString& strFilterIn)
-{
- strCurrentFilter = strFilterIn;
- nTimeFilterUpdated = GetTime();
- fFilterUpdated = true;
- ui->countLabel->setText(QString::fromStdString(strprintf("Please wait... %d", MASTERNODELIST_FILTER_COOLDOWN_SECONDS)));
-}
-
void MasternodeList::on_filterLineEditDIP3_textChanged(const QString& strFilterIn)
{
strCurrentFilterDIP3 = strFilterIn;
@@ -513,181 +220,6 @@ void MasternodeList::on_filterLineEditDIP3_textChanged(const QString& strFilterI
ui->countLabelDIP3->setText(QString::fromStdString(strprintf("Please wait... %d", MASTERNODELIST_FILTER_COOLDOWN_SECONDS)));
}
-void MasternodeList::on_startButton_clicked()
-{
- std::string strAlias;
- {
- LOCK(cs_mymnlist);
- // Find selected node alias
- QItemSelectionModel* selectionModel = ui->tableWidgetMyMasternodes->selectionModel();
- QModelIndexList selected = selectionModel->selectedRows();
-
- if (selected.count() == 0) return;
-
- QModelIndex index = selected.at(0);
- int nSelectedRow = index.row();
- strAlias = ui->tableWidgetMyMasternodes->item(nSelectedRow, 0)->text().toStdString();
- }
-
- // Display message box
- QMessageBox::StandardButton retval = QMessageBox::question(this, tr("Confirm masternode start"),
- tr("Are you sure you want to start masternode %1?").arg(QString::fromStdString(strAlias)),
- QMessageBox::Yes | QMessageBox::Cancel,
- QMessageBox::Cancel);
-
- if (retval != QMessageBox::Yes) return;
-
- WalletModel::EncryptionStatus encStatus = walletModel->getEncryptionStatus();
-
- if (encStatus == walletModel->Locked || encStatus == walletModel->UnlockedForMixingOnly) {
- WalletModel::UnlockContext ctx(walletModel->requestUnlock());
-
- if (!ctx.isValid()) return; // Unlock wallet was cancelled
-
- StartAlias(strAlias);
- return;
- }
-
- StartAlias(strAlias);
-}
-
-void MasternodeList::on_startAllButton_clicked()
-{
- // Display message box
- QMessageBox::StandardButton retval = QMessageBox::question(this, tr("Confirm all masternodes start"),
- tr("Are you sure you want to start ALL masternodes?"),
- QMessageBox::Yes | QMessageBox::Cancel,
- QMessageBox::Cancel);
-
- if (retval != QMessageBox::Yes) return;
-
- WalletModel::EncryptionStatus encStatus = walletModel->getEncryptionStatus();
-
- if (encStatus == walletModel->Locked || encStatus == walletModel->UnlockedForMixingOnly) {
- WalletModel::UnlockContext ctx(walletModel->requestUnlock());
-
- if (!ctx.isValid()) return; // Unlock wallet was cancelled
-
- StartAll();
- return;
- }
-
- StartAll();
-}
-
-void MasternodeList::on_startMissingButton_clicked()
-{
- if (!masternodeSync.IsMasternodeListSynced()) {
- QMessageBox::critical(this, tr("Command is not available right now"),
- tr("You can't use this command until masternode list is synced"));
- return;
- }
-
- // Display message box
- QMessageBox::StandardButton retval = QMessageBox::question(this,
- tr("Confirm missing masternodes start"),
- tr("Are you sure you want to start MISSING masternodes?"),
- QMessageBox::Yes | QMessageBox::Cancel,
- QMessageBox::Cancel);
-
- if (retval != QMessageBox::Yes) return;
-
- WalletModel::EncryptionStatus encStatus = walletModel->getEncryptionStatus();
-
- if (encStatus == walletModel->Locked || encStatus == walletModel->UnlockedForMixingOnly) {
- WalletModel::UnlockContext ctx(walletModel->requestUnlock());
-
- if (!ctx.isValid()) return; // Unlock wallet was cancelled
-
- StartAll("start-missing");
- return;
- }
-
- StartAll("start-missing");
-}
-
-void MasternodeList::on_tableWidgetMyMasternodes_itemSelectionChanged()
-{
- if (ui->tableWidgetMyMasternodes->selectedItems().count() > 0) {
- ui->startButton->setEnabled(true);
- }
-}
-
-void MasternodeList::on_UpdateButton_clicked()
-{
- updateMyNodeList(true);
-}
-
-void MasternodeList::on_QRButton_clicked()
-{
- std::string strAlias;
- {
- LOCK(cs_mymnlist);
- // Find selected node alias
- QItemSelectionModel* selectionModel = ui->tableWidgetMyMasternodes->selectionModel();
- QModelIndexList selected = selectionModel->selectedRows();
-
- if (selected.count() == 0) return;
-
- QModelIndex index = selected.at(0);
- int nSelectedRow = index.row();
- strAlias = ui->tableWidgetMyMasternodes->item(nSelectedRow, 0)->text().toStdString();
- }
-
- ShowQRCode(strAlias);
-}
-
-void MasternodeList::ShowQRCode(std::string strAlias)
-{
- if (!walletModel || !walletModel->getOptionsModel()) return;
-
- // Get private key for this alias
- std::string strMNPrivKey = "";
- std::string strCollateral = "";
- std::string strIP = "";
- CMasternode mn;
- bool fFound = false;
-
- for (const auto& mne : masternodeConfig.getEntries()) {
- if (strAlias == mne.getAlias()) {
- strMNPrivKey = mne.getPrivKey();
- strCollateral = mne.getTxHash() + "-" + mne.getOutputIndex();
- strIP = mne.getIp();
- fFound = mnodeman.Get(COutPoint(uint256S(mne.getTxHash()), atoi(mne.getOutputIndex())), mn);
- break;
- }
- }
-
- // Title of popup window
- QString strWindowtitle = tr("Additional information for Masternode %1").arg(QString::fromStdString(strAlias));
-
- // Title above QR-Code
- QString strQRCodeTitle = tr("Masternode Private Key");
-
- // Create dialog text as HTML
- QString strHTML = "";
- strHTML += "" + tr("Alias") + ": " + GUIUtil::HtmlEscape(strAlias) + "
";
- strHTML += "" + tr("Private Key") + ": " + GUIUtil::HtmlEscape(strMNPrivKey) + "
";
- strHTML += "" + tr("Collateral") + ": " + GUIUtil::HtmlEscape(strCollateral) + "
";
- strHTML += "" + tr("IP") + ": " + GUIUtil::HtmlEscape(strIP) + "
";
- if (fFound) {
- strHTML += "" + tr("Protocol") + ": " + QString::number(mn.nProtocolVersion) + "
";
- strHTML += "" + tr("Version") + ": " + (mn.lastPing.nDaemonVersion > DEFAULT_DAEMON_VERSION ? GUIUtil::HtmlEscape(FormatVersion(mn.lastPing.nDaemonVersion)) : tr("Unknown")) + "
";
- strHTML += "" + tr("Sentinel") + ": " + (mn.lastPing.nSentinelVersion > DEFAULT_SENTINEL_VERSION ? GUIUtil::HtmlEscape(SafeIntVersionToString(mn.lastPing.nSentinelVersion)) : tr("Unknown")) + "
";
- strHTML += "" + tr("Status") + ": " + GUIUtil::HtmlEscape(CMasternode::StateToString(mn.nActiveState)) + "
";
- strHTML += "" + tr("Payee") + ": " + GUIUtil::HtmlEscape(CBitcoinAddress(mn.pubKeyCollateralAddress.GetID()).ToString()) + "
";
- strHTML += "" + tr("Active") + ": " + GUIUtil::HtmlEscape(DurationToDHMS(mn.lastPing.sigTime - mn.sigTime)) + "
";
- strHTML += "" + tr("Last Seen") + ": " + GUIUtil::HtmlEscape(DateTimeStrFormat("%Y-%m-%d %H:%M", mn.lastPing.sigTime + GetOffsetFromUtc())) + "
";
- }
-
- // Open QR dialog
- QRDialog* dialog = new QRDialog(this);
- dialog->setAttribute(Qt::WA_DeleteOnClose);
- dialog->setModel(walletModel->getOptionsModel());
- dialog->setInfo(strWindowtitle, QString::fromStdString(strMNPrivKey), strHTML, strQRCodeTitle);
- dialog->show();
-}
-
CDeterministicMNCPtr MasternodeList::GetSelectedDIP3MN()
{
std::string strProTxHash;
diff --git a/src/qt/masternodelist.h b/src/qt/masternodelist.h
index 5532c94e661c..0c19830eafe2 100644
--- a/src/qt/masternodelist.h
+++ b/src/qt/masternodelist.h
@@ -12,7 +12,6 @@
#include
#include
-#define MY_MASTERNODELIST_UPDATE_SECONDS 60
#define MASTERNODELIST_UPDATE_SECONDS 15
#define MASTERNODELIST_FILTER_COOLDOWN_SECONDS 3
@@ -39,23 +38,14 @@ class MasternodeList : public QWidget
void setClientModel(ClientModel* clientModel);
void setWalletModel(WalletModel* walletModel);
- void ShowQRCode(std::string strAlias);
- void StartAlias(std::string strAlias);
- void StartAll(std::string strCommand = "start-all");
CDeterministicMNCPtr GetSelectedDIP3MN();
private:
- QMenu* contextMenu;
QMenu* contextMenuDIP3;
- int64_t nTimeFilterUpdated;
int64_t nTimeFilterUpdatedDIP3;
- bool fFilterUpdated;
bool fFilterUpdatedDIP3;
public Q_SLOTS:
- void updateMyMasternodeInfo(QString strAlias, QString strAddr, const COutPoint& outpoint);
- void updateMyNodeList(bool fForce = false);
- void updateNodeList();
void updateDIP3List();
Q_SIGNALS:
@@ -67,29 +57,14 @@ public Q_SLOTS:
ClientModel* clientModel;
WalletModel* walletModel;
- // Protects tableWidgetMasternodes
- CCriticalSection cs_mnlist;
-
- // Protects tableWidgetMyMasternodes
- CCriticalSection cs_mymnlist;
-
// Protects tableWidgetMasternodesDIP3
CCriticalSection cs_dip3list;
- QString strCurrentFilter;
QString strCurrentFilterDIP3;
private Q_SLOTS:
- void showContextMenu(const QPoint&);
void showContextMenuDIP3(const QPoint&);
- void on_filterLineEdit_textChanged(const QString& strFilterIn);
void on_filterLineEditDIP3_textChanged(const QString& strFilterIn);
- void on_QRButton_clicked();
- void on_startButton_clicked();
- void on_startAllButton_clicked();
- void on_startMissingButton_clicked();
- void on_tableWidgetMyMasternodes_itemSelectionChanged();
- void on_UpdateButton_clicked();
void extraInfoDIP3_clicked();
void copyProTxHash_clicked();
diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp
index 27b68fe2c02c..5f53ab639da3 100644
--- a/src/qt/optionsmodel.cpp
+++ b/src/qt/optionsmodel.cpp
@@ -23,7 +23,6 @@
#include "wallet/wallet.h"
#include "wallet/walletdb.h"
-#include "masternodeconfig.h"
#include "privatesend-client.h"
#endif
@@ -93,9 +92,6 @@ void OptionsModel::Init(bool resetSettings)
if (!settings.contains("digits"))
settings.setValue("digits", "2");
- if (!settings.contains("fShowMasternodesTab"))
- settings.setValue("fShowMasternodesTab", masternodeConfig.getCount());
-
// PrivateSend
if (!settings.contains("fShowAdvancedPSUI"))
settings.setValue("fShowAdvancedPSUI", false);
diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp
index 16239a947643..8fe72c9c731c 100644
--- a/src/qt/walletview.cpp
+++ b/src/qt/walletview.cpp
@@ -9,7 +9,6 @@
#include "bitcoingui.h"
#include "clientmodel.h"
#include "guiutil.h"
-#include "masternodeconfig.h"
#include "optionsmodel.h"
#include "overviewpage.h"
#include "platformstyle.h"
diff --git a/src/rpc/governance.cpp b/src/rpc/governance.cpp
index d5bdf80bfac3..5229485b6b79 100644
--- a/src/rpc/governance.cpp
+++ b/src/rpc/governance.cpp
@@ -12,10 +12,7 @@
#include "governance-validators.h"
#include "init.h"
#include "validation.h"
-#include "masternode.h"
#include "masternode-sync.h"
-#include "masternodeconfig.h"
-#include "masternodeman.h"
#include "messagesigner.h"
#include "rpc/server.h"
#include "util.h"
@@ -261,9 +258,10 @@ UniValue gobject_submit(const JSONRPCRequest& request)
throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Must wait for client to sync with masternode network. Try again in a minute or so.");
}
- bool fMnFound = mnodeman.Has(activeMasternodeInfo.outpoint);
+ auto mnList = deterministicMNManager->GetListAtChainTip();
+ bool fMnFound = mnList.HasValidMNByCollateral(activeMasternodeInfo.outpoint);
- DBG( std::cout << "gobject: submit activeMasternodeInfo.keyIDOperator = " << activeMasternodeInfo.legacyKeyIDOperator.ToString()
+ DBG( std::cout << "gobject: submit activeMasternodeInfo.pubKeyOperator = " << (activeMasternodeInfo.blsPubKeyOperator ? activeMasternodeInfo.blsPubKeyOperator->ToString() : "N/A")
<< ", outpoint = " << activeMasternodeInfo.outpoint.ToStringShort()
<< ", params.size() = " << request.params.size()
<< ", fMnFound = " << fMnFound << std::endl; );
@@ -313,11 +311,7 @@ UniValue gobject_submit(const JSONRPCRequest& request)
if (govobj.GetObjectType() == GOVERNANCE_OBJECT_TRIGGER) {
if (fMnFound) {
govobj.SetMasternodeOutpoint(activeMasternodeInfo.outpoint);
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
- govobj.Sign(*activeMasternodeInfo.blsKeyOperator);
- } else {
- govobj.Sign(activeMasternodeInfo.legacyKeyOperator, activeMasternodeInfo.legacyKeyIDOperator);
- }
+ govobj.Sign(*activeMasternodeInfo.blsKeyOperator);
} else {
LogPrintf("gobject(submit) -- Object submission rejected because node is not a masternode\n");
throw JSONRPCError(RPC_INVALID_PARAMETER, "Only valid masternodes can submit this type of object");
@@ -412,10 +406,9 @@ UniValue gobject_vote_conf(const JSONRPCRequest& request)
UniValue statusObj(UniValue::VOBJ);
UniValue returnObj(UniValue::VOBJ);
- CMasternode mn;
- bool fMnFound = mnodeman.Get(activeMasternodeInfo.outpoint, mn);
+ auto dmn = deterministicMNManager->GetListAtChainTip().GetValidMNByCollateral(activeMasternodeInfo.outpoint);
- if (!fMnFound) {
+ if (!dmn) {
nFailed++;
statusObj.push_back(Pair("result", "failed"));
statusObj.push_back(Pair("errorMessage", "Can't find masternode by collateral output"));
@@ -425,19 +418,16 @@ UniValue gobject_vote_conf(const JSONRPCRequest& request)
return returnObj;
}
- CGovernanceVote vote(mn.outpoint, hash, eVoteSignal, eVoteOutcome);
+ CGovernanceVote vote(dmn->collateralOutpoint, hash, eVoteSignal, eVoteOutcome);
bool signSuccess = false;
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
- if (govObjType == GOVERNANCE_OBJECT_PROPOSAL && eVoteSignal == VOTE_SIGNAL_FUNDING) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Can't use vote-conf for proposals when deterministic masternodes are active");
- }
- if (activeMasternodeInfo.blsKeyOperator) {
- signSuccess = vote.Sign(*activeMasternodeInfo.blsKeyOperator);
- }
- } else {
- signSuccess = vote.Sign(activeMasternodeInfo.legacyKeyOperator, activeMasternodeInfo.legacyKeyIDOperator);
+ if (govObjType == GOVERNANCE_OBJECT_PROPOSAL && eVoteSignal == VOTE_SIGNAL_FUNDING) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Can't use vote-conf for proposals");
+ }
+ if (activeMasternodeInfo.blsKeyOperator) {
+ signSuccess = vote.Sign(*activeMasternodeInfo.blsKeyOperator);
}
+
if (!signSuccess) {
nFailed++;
statusObj.push_back(Pair("result", "failed"));
@@ -466,9 +456,9 @@ UniValue gobject_vote_conf(const JSONRPCRequest& request)
return returnObj;
}
-UniValue VoteWithMasternodeList(const std::vector& entries,
- const uint256& hash, vote_signal_enum_t eVoteSignal,
- vote_outcome_enum_t eVoteOutcome)
+UniValue VoteWithMasternodes(const std::map& keys,
+ const uint256& hash, vote_signal_enum_t eVoteSignal,
+ vote_outcome_enum_t eVoteOutcome)
{
int govObjType;
{
@@ -483,59 +473,31 @@ UniValue VoteWithMasternodeList(const std::vectorGetListAtChainTip();
+
UniValue resultsObj(UniValue::VOBJ);
- for (const auto& mne : entries) {
- CPubKey pubKeyOperator;
- CKey keyOperator;
+ for (const auto& p : keys) {
+ const auto& proTxHash = p.first;
+ const auto& key = p.second;
UniValue statusObj(UniValue::VOBJ);
- if (!CMessageSigner::GetKeysFromSecret(mne.getPrivKey(), keyOperator, pubKeyOperator)) {
- nFailed++;
- statusObj.push_back(Pair("result", "failed"));
- statusObj.push_back(Pair("errorMessage", "Masternode signing error, could not set key correctly"));
- resultsObj.push_back(Pair(mne.getAlias(), statusObj));
- continue;
- }
-
- uint256 nTxHash;
- nTxHash.SetHex(mne.getTxHash());
-
- int nOutputIndex = 0;
- if (!ParseInt32(mne.getOutputIndex(), &nOutputIndex)) {
- continue;
- }
-
- COutPoint outpoint(nTxHash, nOutputIndex);
-
- CMasternode mn;
- bool fMnFound = mnodeman.Get(outpoint, mn);
-
- if (!fMnFound) {
+ auto dmn = mnList.GetValidMN(proTxHash);
+ if (!dmn) {
nFailed++;
statusObj.push_back(Pair("result", "failed"));
- statusObj.push_back(Pair("errorMessage", "Can't find masternode by collateral output"));
- resultsObj.push_back(Pair(mne.getAlias(), statusObj));
+ statusObj.push_back(Pair("errorMessage", "Can't find masternode by proTxHash"));
+ resultsObj.push_back(Pair(proTxHash.ToString(), statusObj));
continue;
}
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
- if (govObjType == GOVERNANCE_OBJECT_PROPOSAL && mn.keyIDVoting != pubKeyOperator.GetID()) {
- nFailed++;
- statusObj.push_back(Pair("result", "failed"));
- statusObj.push_back(Pair("errorMessage", "Can't vote on proposal when key does not match voting key"));
- resultsObj.push_back(Pair(mne.getAlias(), statusObj));
- continue;
- }
- }
-
- CGovernanceVote vote(mn.outpoint, hash, eVoteSignal, eVoteOutcome);
- if (!vote.Sign(keyOperator, pubKeyOperator.GetID())) {
+ CGovernanceVote vote(dmn->collateralOutpoint, hash, eVoteSignal, eVoteOutcome);
+ if (!vote.Sign(key, key.GetPubKey().GetID())) {
nFailed++;
statusObj.push_back(Pair("result", "failed"));
statusObj.push_back(Pair("errorMessage", "Failure to sign."));
- resultsObj.push_back(Pair(mne.getAlias(), statusObj));
+ resultsObj.push_back(Pair(proTxHash.ToString(), statusObj));
continue;
}
@@ -549,7 +511,7 @@ UniValue VoteWithMasternodeList(const std::vector \n"
- "Vote on a governance object by all masternodes (using masternode.conf setup)\n"
+ "Vote on a governance object by all masternodes for which the voting key is present in the local wallet\n"
"\nArguments:\n"
"1. governance-hash (string, required) hash of the governance object\n"
"2. vote (string, required) vote, possible values: [funding|valid|delete|endorsed]\n"
@@ -592,66 +555,33 @@ UniValue gobject_vote_many(const JSONRPCRequest& request)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid vote outcome. Please use one of the following: 'yes', 'no' or 'abstain'");
}
- std::vector entries = masternodeConfig.getEntries();
-
-#ifdef ENABLE_WALLET
- // This is a hack to maintain code-level backwards compatibility with masternode.conf and the deterministic masternodes.
- // Deterministic masternode keys are managed inside the wallet instead of masternode.conf
- // This allows voting on proposals when you have the MN voting key in your wallet
- // We can remove this when we remove support for masternode.conf and only support wallet based masternode
- // management
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
- if (!pwalletMain) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "vote-many not supported when wallet is disabled.");
- }
- entries.clear();
-
- auto mnList = deterministicMNManager->GetListAtChainTip();
- mnList.ForEachMN(true, [&](const CDeterministicMNCPtr& dmn) {
- bool found = false;
- for (const auto &mne : entries) {
- uint256 nTxHash;
- nTxHash.SetHex(mne.getTxHash());
-
- int nOutputIndex = 0;
- if(!ParseInt32(mne.getOutputIndex(), &nOutputIndex)) {
- continue;
- }
-
- if (nTxHash == dmn->collateralOutpoint.hash && (uint32_t)nOutputIndex == dmn->collateralOutpoint.n) {
- found = true;
- break;
- }
- }
- if (!found) {
- CKey ownerKey;
- if (pwalletMain->GetKey(dmn->pdmnState->keyIDVoting, ownerKey)) {
- CBitcoinSecret secret(ownerKey);
- CMasternodeConfig::CMasternodeEntry mne(dmn->proTxHash.ToString(), dmn->pdmnState->addr.ToStringIPPort(false), secret.ToString(), dmn->collateralOutpoint.hash.ToString(), itostr(dmn->collateralOutpoint.n));
- entries.push_back(mne);
- }
- }
- });
- }
-#else
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
+ if (!pwalletMain) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "vote-many not supported when wallet is disabled.");
}
-#endif
- return VoteWithMasternodeList(entries, hash, eVoteSignal, eVoteOutcome);
+ std::map votingKeys;
+
+ auto mnList = deterministicMNManager->GetListAtChainTip();
+ mnList.ForEachMN(true, [&](const CDeterministicMNCPtr& dmn) {
+ CKey votingKey;
+ if (pwalletMain->GetKey(dmn->pdmnState->keyIDVoting, votingKey)) {
+ votingKeys.emplace(dmn->proTxHash, votingKey);
+ }
+ });
+
+ return VoteWithMasternodes(votingKeys, hash, eVoteSignal, eVoteOutcome);
}
void gobject_vote_alias_help()
{
throw std::runtime_error(
"gobject vote-alias \n"
- "Vote on a governance object by masternode alias (using masternode.conf setup)\n"
+ "Vote on a governance object by masternode's voting key (if present in local wallet)\n"
"\nArguments:\n"
"1. governance-hash (string, required) hash of the governance object\n"
"2. vote (string, required) vote, possible values: [funding|valid|delete|endorsed]\n"
"3. vote-outcome (string, required) vote outcome, possible values: [yes|no|abstain]\n"
- "4. alias-name (string, required) masternode alias or proTxHash after DIP3 activation"
+ "4. protx-hash (string, required) masternode's proTxHash"
);
}
@@ -676,41 +606,27 @@ UniValue gobject_vote_alias(const JSONRPCRequest& request)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid vote outcome. Please use one of the following: 'yes', 'no' or 'abstain'");
}
- std::vector entries;
-
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
-#ifdef ENABLE_WALLET
- if (!pwalletMain) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "vote-alias not supported when wallet is disabled");
- }
-
- uint256 proTxHash = ParseHashV(request.params[4], "alias-name");
- auto dmn = deterministicMNManager->GetListAtChainTip().GetValidMN(proTxHash);
- if (!dmn) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid or unknown proTxHash");
- }
+ if (!pwalletMain) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "vote-alias not supported when wallet is disabled");
+ }
- CKey votingKey;
- if (!pwalletMain->GetKey(dmn->pdmnState->keyIDVoting, votingKey)) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Voting ekey %s not known by wallet", CBitcoinAddress(dmn->pdmnState->keyIDVoting).ToString()));
- }
+ uint256 proTxHash = ParseHashV(request.params[4], "protx-hash");
+ auto dmn = deterministicMNManager->GetListAtChainTip().GetValidMN(proTxHash);
+ if (!dmn) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid or unknown proTxHash");
+ }
- CBitcoinSecret secret(votingKey);
- CMasternodeConfig::CMasternodeEntry mne(dmn->proTxHash.ToString(), dmn->pdmnState->addr.ToStringIPPort(false), secret.ToString(), dmn->collateralOutpoint.hash.ToString(), itostr(dmn->collateralOutpoint.n));
- entries.push_back(mne);
-#else
- throw JSONRPCError(RPC_INVALID_PARAMETER, "vote-alias not supported when wallet is disabled");
-#endif
- } else {
- std::string strAlias = request.params[4].get_str();
- for (const auto& mne : masternodeConfig.getEntries()) {
- if (strAlias == mne.getAlias())
- entries.push_back(mne);
- }
+ CKey votingKey;
+ if (!pwalletMain->GetKey(dmn->pdmnState->keyIDVoting, votingKey)) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Voting key %s not known by wallet", CBitcoinAddress(dmn->pdmnState->keyIDVoting).ToString()));
}
- return VoteWithMasternodeList(entries, hash, eVoteSignal, eVoteOutcome);
+ std::map votingKeys;
+ votingKeys.emplace(proTxHash, votingKey);
+
+ return VoteWithMasternodes(votingKeys, hash, eVoteSignal, eVoteOutcome);
}
+#endif
UniValue ListObjects(const std::string& strCachedSignal, const std::string& strType, int nStartTime)
{
@@ -1024,9 +940,9 @@ UniValue gobject_getcurrentvotes(const JSONRPCRequest& request)
" getcurrentvotes - Get only current (tallying) votes for a governance object hash (does not include old votes)\n"
" list - List governance objects (can be filtered by signal and/or object type)\n"
" diff - List differences since last diff\n"
- " vote-alias - Vote on a governance object by masternode alias (using masternode.conf setup)\n"
+ " vote-alias - Vote on a governance object by masternode alias/proTxHash\n"
" vote-conf - Vote on a governance object by masternode configured in dash.conf\n"
- " vote-many - Vote on a governance object by all masternodes (using masternode.conf setup)\n"
+ " vote-many - Vote on a governance object by all masternodes for which the voting key is in the wallet\n"
);
}
@@ -1063,10 +979,12 @@ UniValue gobject(const JSONRPCRequest& request)
return gobject_submit(request);
} else if (strCommand == "vote-conf") {
return gobject_vote_conf(request);
+#ifdef ENABLE_WALLET
} else if (strCommand == "vote-many") {
return gobject_vote_many(request);
} else if (strCommand == "vote-alias") {
return gobject_vote_alias(request);
+#endif
} else if (strCommand == "list") {
// USERS CAN QUERY THE SYSTEM FOR A LIST OF VARIOUS GOVERNANCE ITEMS
return gobject_list(request);
@@ -1133,10 +1051,9 @@ UniValue voteraw(const JSONRPCRequest& request)
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Malformed base64 encoding");
}
- CMasternode mn;
- bool fMnFound = mnodeman.Get(outpoint, mn);
+ auto dmn = deterministicMNManager->GetListAtChainTip().GetValidMNByCollateral(outpoint);
- if (!fMnFound) {
+ if (!dmn) {
throw JSONRPCError(RPC_INTERNAL_ERROR, "Failure to find masternode in list : " + outpoint.ToStringShort());
}
@@ -1189,8 +1106,6 @@ UniValue getgovernanceinfo(const JSONRPCRequest& request)
UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("governanceminquorum", Params().GetConsensus().nGovernanceMinQuorum));
- obj.push_back(Pair("masternodewatchdogmaxseconds", MASTERNODE_SENTINEL_PING_MAX_SECONDS));
- obj.push_back(Pair("sentinelpingmaxseconds", MASTERNODE_SENTINEL_PING_MAX_SECONDS));
obj.push_back(Pair("proposalfee", ValueFromAmount(GOVERNANCE_PROPOSAL_FEE_TX)));
obj.push_back(Pair("superblockcycle", Params().GetConsensus().nSuperblockCycle));
obj.push_back(Pair("lastsuperblock", nLastSuperblock));
diff --git a/src/rpc/masternode.cpp b/src/rpc/masternode.cpp
index f443a0527c00..a3c54310ce7b 100644
--- a/src/rpc/masternode.cpp
+++ b/src/rpc/masternode.cpp
@@ -10,8 +10,6 @@
#include "validation.h"
#include "masternode-payments.h"
#include "masternode-sync.h"
-#include "masternodeconfig.h"
-#include "masternodeman.h"
#ifdef ENABLE_WALLET
#include "privatesend-client.h"
#endif // ENABLE_WALLET
@@ -24,8 +22,6 @@
#include "evo/specialtx.h"
#include "evo/deterministicmns.h"
-#include "evo/deterministicmns.h"
-
#include
#include
#include
@@ -99,13 +95,13 @@ UniValue getpoolinfo(const JSONRPCRequest& request)
// obj.push_back(Pair("entries", pprivateSendBase->GetEntriesCount()));
obj.push_back(Pair("status", privateSendClient.GetStatuses()));
- std::vector vecMnInfo;
- if (privateSendClient.GetMixingMasternodesInfo(vecMnInfo)) {
+ std::vector vecDmns;
+ if (privateSendClient.GetMixingMasternodesInfo(vecDmns)) {
UniValue pools(UniValue::VARR);
- for (const auto& mnInfo : vecMnInfo) {
+ for (const auto& dmn : vecDmns) {
UniValue pool(UniValue::VOBJ);
- pool.push_back(Pair("outpoint", mnInfo.outpoint.ToStringShort()));
- pool.push_back(Pair("addr", mnInfo.addr.ToString()));
+ pool.push_back(Pair("outpoint", dmn->collateralOutpoint.ToStringShort()));
+ pool.push_back(Pair("addr", dmn->pdmnState->addr.ToString()));
pools.push_back(pool);
}
obj.push_back(Pair("pools", pools));
@@ -136,26 +132,20 @@ void masternode_list_help()
"2. \"filter\" (string, optional) Filter results. Partial match by outpoint by default in all modes,\n"
" additional matches in some modes are also available\n"
"\nAvailable modes:\n"
- " activeseconds - Print number of seconds masternode recognized by the network as enabled\n"
- " (since latest issued \"masternode start/start-many/start-alias\")\n"
" addr - Print ip address associated with a masternode (can be additionally filtered, partial match)\n"
- " daemon - Print daemon version of a masternode (can be additionally filtered, exact match)\n"
- " full - Print info in format 'status protocol payee lastseen activeseconds lastpaidtime lastpaidblock IP'\n"
+ " full - Print info in format 'status payee lastpaidtime lastpaidblock IP'\n"
" (can be additionally filtered, partial match)\n"
- " info - Print info in format 'status protocol payee lastseen activeseconds sentinelversion sentinelstate IP'\n"
+ " info - Print info in format 'status payee IP'\n"
" (can be additionally filtered, partial match)\n"
" json - Print info in JSON format (can be additionally filtered, partial match)\n"
" lastpaidblock - Print the last block height a node was paid on the network\n"
" lastpaidtime - Print the last time a node was paid on the network\n"
- " lastseen - Print timestamp of when a masternode was last seen on the network\n"
" payee - Print Dash address associated with a masternode (can be additionally filtered,\n"
" partial match)\n"
- " protocol - Print protocol of a masternode (can be additionally filtered, exact match)\n"
" keyid - Print the masternode (not collateral) key id\n"
" rank - Print rank of a masternode based on current block\n"
- " sentinel - Print sentinel version of a masternode (can be additionally filtered, exact match)\n"
- " status - Print masternode status: PRE_ENABLED / ENABLED / EXPIRED / SENTINEL_PING_EXPIRED / NEW_START_REQUIRED /\n"
- " UPDATE_REQUIRED / POSE_BAN / OUTPOINT_SPENT (can be additionally filtered, partial match)\n"
+ " status - Print masternode status: ENABED / POSE_BAN / OUTPOINT_SPENT\n"
+ " (can be additionally filtered, partial match)\n"
);
}
@@ -224,25 +214,15 @@ UniValue masternode_count(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() > 2)
masternode_count_help();
- int nCount;
- int total = mnodeman.CountMasternodes(0);
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
- nCount = mnodeman.CountEnabled();
- } else {
- masternode_info_t mnInfo;
- mnodeman.GetNextMasternodeInQueueForPayment(true, nCount, mnInfo);
- }
-
- int ps = mnodeman.CountEnabled(MIN_PRIVATESEND_PEER_PROTO_VERSION);
- int enabled = mnodeman.CountEnabled();
+ auto mnList = deterministicMNManager->GetListAtChainTip();
+ int total = mnList.GetAllMNsCount();
+ int enabled = mnList.GetValidMNsCount();
if (request.params.size() == 1) {
UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("total", total));
- obj.push_back(Pair("ps_compatible", ps));
obj.push_back(Pair("enabled", enabled));
- obj.push_back(Pair("qualify", nCount));
return obj;
}
@@ -252,47 +232,24 @@ UniValue masternode_count(const JSONRPCRequest& request)
if (strMode == "total")
return total;
- if (strMode == "ps")
- return ps;
-
if (strMode == "enabled")
return enabled;
- if (strMode == "qualify")
- return nCount;
-
if (strMode == "all")
- return strprintf("Total: %d (PS Compatible: %d / Enabled: %d / Qualify: %d)",
- total, ps, enabled, nCount);
+ return strprintf("Total: %d (Enabled: %d)",
+ total, enabled);
throw JSONRPCError(RPC_INVALID_PARAMETER, "Unknown mode value");
}
UniValue GetNextMasternodeForPayment(int heightShift)
{
- int nCount;
- int nHeight;
- masternode_info_t mnInfo;
- CBlockIndex* pindex = NULL;
- {
- LOCK(cs_main);
- pindex = chainActive.Tip();
- }
-
- nHeight = pindex->nHeight + heightShift;
- mnodeman.UpdateLastPaid(pindex);
-
- CScript payeeScript;
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
- auto payee = deterministicMNManager->GetListAtChainTip().GetMNPayee();
- if (!payee || !mnodeman.GetMasternodeInfo(payee->proTxHash, mnInfo))
- return "unknown";
- payeeScript = payee->pdmnState->scriptPayout;
- } else {
- if (!mnodeman.GetNextMasternodeInQueueForPayment(nHeight, true, nCount, mnInfo))
- return "unknown";
- payeeScript = GetScriptForDestination(mnInfo.keyIDCollateralAddress);
- }
+ auto mnList = deterministicMNManager->GetListAtChainTip();
+ auto payees = mnList.GetProjectedMNPayees(heightShift);
+ if (payees.empty())
+ return "unknown";
+ auto payee = payees[heightShift - 9];
+ CScript payeeScript = payee->pdmnState->scriptPayout;
CTxDestination payeeDest;
CBitcoinAddress payeeAddr;
@@ -302,13 +259,11 @@ UniValue GetNextMasternodeForPayment(int heightShift)
UniValue obj(UniValue::VOBJ);
- obj.push_back(Pair("height", nHeight));
- obj.push_back(Pair("IP:port", mnInfo.addr.ToString()));
- obj.push_back(Pair("protocol", mnInfo.nProtocolVersion));
- obj.push_back(Pair("outpoint", mnInfo.outpoint.ToStringShort()));
+ obj.push_back(Pair("height", mnList.GetHeight() + heightShift));
+ obj.push_back(Pair("IP:port", payee->pdmnState->addr.ToString()));
+ obj.push_back(Pair("proTxHash", payee->proTxHash.ToString()));
+ obj.push_back(Pair("outpoint", payee->collateralOutpoint.ToStringShort()));
obj.push_back(Pair("payee", payeeAddr.IsValid() ? payeeAddr.ToString() : "UNKNOWN"));
- obj.push_back(Pair("lastseen", mnInfo.nTimeLastPing));
- obj.push_back(Pair("activeseconds", mnInfo.nTimeLastPing - mnInfo.sigTime));
return obj;
}
@@ -345,210 +300,6 @@ UniValue masternode_current(const JSONRPCRequest& request)
}
#ifdef ENABLE_WALLET
-void masternode_start_alias_help()
-{
- throw std::runtime_error(
- "masternode start-alias \"alias\"\n"
- "Start single remote masternode by assigned alias\n"
- "\nArguments:\n"
- "1. \"alias\" (string, required) The alias of the remote masternode configured in masternode.conf\n"
- );
-}
-
-UniValue masternode_start_alias(const JSONRPCRequest& request)
-{
- if (request.fHelp || request.params.size() < 2)
- masternode_start_alias_help();
- if (deterministicMNManager->IsDeterministicMNsSporkActive())
- throw JSONRPCError(RPC_MISC_ERROR, "start-alias is not supported when deterministic masternode list is active (DIP3)");
-
- if (!EnsureWalletIsAvailable(request.fHelp))
- return NullUniValue;
-
- {
- LOCK(pwalletMain->cs_wallet);
- EnsureWalletIsUnlocked();
- }
-
- std::string strAlias = request.params[1].get_str();
-
- bool fFound = false;
-
- UniValue statusObj(UniValue::VOBJ);
- statusObj.push_back(Pair("alias", strAlias));
-
- for (const auto& mne : masternodeConfig.getEntries()) {
- if (mne.getAlias() == strAlias) {
- fFound = true;
- std::string strError;
- CMasternodeBroadcast mnb;
-
- bool fResult = CMasternodeBroadcast::Create(mne.getIp(), mne.getPrivKey(), mne.getTxHash(), mne.getOutputIndex(), strError, mnb);
-
- int nDoS;
- if (fResult && !mnodeman.CheckMnbAndUpdateMasternodeList(NULL, mnb, nDoS, *g_connman)) {
- strError = "Failed to verify MNB";
- fResult = false;
- }
-
- statusObj.push_back(Pair("result", fResult ? "successful" : "failed"));
- if (!fResult) {
- statusObj.push_back(Pair("errorMessage", strError));
- }
- mnodeman.NotifyMasternodeUpdates(*g_connman);
- break;
- }
- }
-
- if (!fFound) {
- statusObj.push_back(Pair("result", "failed"));
- statusObj.push_back(Pair("errorMessage", "Could not find alias in config. Verify with list-conf."));
- }
-
- return statusObj;
-}
-
-void masternode_start_all_help()
-{
- throw std::runtime_error(
- "masternode start-all\n"
- "Start remote masternodes configured in masternode.conf\n"
- );
-}
-
-UniValue StartMasternodeList(const std::vector& entries)
-{
- int nSuccessful = 0;
- int nFailed = 0;
-
- UniValue resultsObj(UniValue::VOBJ);
-
- for (const auto& mne : entries) {
- std::string strError;
- CMasternodeBroadcast mnb;
-
- bool fResult = CMasternodeBroadcast::Create(mne.getIp(), mne.getPrivKey(), mne.getTxHash(), mne.getOutputIndex(), strError, mnb);
-
- int nDoS;
- if (fResult && !mnodeman.CheckMnbAndUpdateMasternodeList(NULL, mnb, nDoS, *g_connman)) {
- strError = "Failed to verify MNB";
- fResult = false;
- }
-
- UniValue statusObj(UniValue::VOBJ);
- statusObj.push_back(Pair("alias", mne.getAlias()));
- statusObj.push_back(Pair("result", fResult ? "successful" : "failed"));
-
- if (fResult) {
- nSuccessful++;
- } else {
- nFailed++;
- statusObj.push_back(Pair("errorMessage", strError));
- }
-
- resultsObj.push_back(Pair("status", statusObj));
- }
- mnodeman.NotifyMasternodeUpdates(*g_connman);
-
- UniValue returnObj(UniValue::VOBJ);
- returnObj.push_back(Pair("overall", strprintf("Successfully started %d masternodes, failed to start %d, total %d", nSuccessful, nFailed, nSuccessful + nFailed)));
- returnObj.push_back(Pair("detail", resultsObj));
-
- return returnObj;
-}
-
-UniValue masternode_start_all(const JSONRPCRequest& request)
-{
- if (request.fHelp)
- masternode_start_all_help();
- if (deterministicMNManager->IsDeterministicMNsSporkActive())
- throw JSONRPCError(RPC_MISC_ERROR, strprintf("start-all is not supported when deterministic masternode list is active (DIP3)"));
-
- if (!EnsureWalletIsAvailable(request.fHelp))
- return NullUniValue;
-
- {
- LOCK(pwalletMain->cs_wallet);
- EnsureWalletIsUnlocked();
- }
-
- return StartMasternodeList(masternodeConfig.getEntries());
-}
-
-void masternode_start_missing_help()
-{
- throw std::runtime_error(
- "masternode start-missing\n"
- "Start not started remote masternodes configured in masternode.conf\n"
- );
-}
-
-UniValue masternode_start_missing(const JSONRPCRequest& request)
-{
- if (request.fHelp)
- masternode_start_missing_help();
-
- if (!EnsureWalletIsAvailable(request.fHelp))
- return NullUniValue;
-
- {
- LOCK(pwalletMain->cs_wallet);
- EnsureWalletIsUnlocked();
- }
-
- if (!masternodeSync.IsMasternodeListSynced()) {
- throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "You can't use this command until masternode list is synced");
- }
-
- std::vector entries;
- for (const auto& mne : masternodeConfig.getEntries()) {
- COutPoint outpoint = COutPoint(uint256S(mne.getTxHash()), (uint32_t)atoi(mne.getOutputIndex()));
- CMasternode mn;
- bool fFound = mnodeman.Get(outpoint, mn);
- if (fFound)
- entries.push_back(mne);
- }
- return StartMasternodeList(entries);
-}
-
-void masternode_start_disabled_help()
-{
- throw std::runtime_error(
- "masternode start-disabled\n"
- "Start not started and disabled remote masternodes configured in masternode.conf\n"
- );
-}
-
-UniValue masternode_start_disabled(const JSONRPCRequest& request)
-{
- if (request.fHelp)
- masternode_start_disabled_help();
-
- if (!EnsureWalletIsAvailable(request.fHelp))
- return NullUniValue;
-
- {
- LOCK(pwalletMain->cs_wallet);
- EnsureWalletIsUnlocked();
- }
-
- if (!masternodeSync.IsMasternodeListSynced()) {
- throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "You can't use this command until masternode list is synced");
- }
-
- std::vector entries;
- for (const auto& mne : masternodeConfig.getEntries()) {
- COutPoint outpoint = COutPoint(uint256S(mne.getTxHash()), (uint32_t)atoi(mne.getOutputIndex()));
- CMasternode mn;
- bool fFound = mnodeman.Get(outpoint, mn);
-
- if (fFound && mn.IsEnabled()) continue;
-
- entries.push_back(mne);
- }
- return StartMasternodeList(entries);
-}
-
void masternode_outputs_help()
{
throw std::runtime_error(
@@ -579,67 +330,6 @@ UniValue masternode_outputs(const JSONRPCRequest& request)
#endif // ENABLE_WALLET
-void masternode_genkey_help()
-{
- throw std::runtime_error(
- "masternode genkey (compressed)\n"
- "Generate new masternodeprivkey\n"
- "\nArguments:\n"
- "1. compressed (boolean, optional, default=false) generate compressed privkey\n"
- );
-}
-
-UniValue masternode_genkey(const JSONRPCRequest& request)
-{
- if (request.fHelp)
- masternode_genkey_help();
-
- bool fCompressed = false;
- if (request.params.size() > 1) {
- fCompressed = ParseBoolV(request.params[1], "compressed");
- }
-
- CKey secret;
- secret.MakeNewKey(fCompressed);
-
- return CBitcoinSecret(secret).ToString();
-}
-
-void masternode_list_conf_help()
-{
- throw std::runtime_error(
- "masternode list-conf\n"
- "Print masternode.conf in JSON format\n"
- );
-}
-
-UniValue masternode_list_conf(const JSONRPCRequest& request)
-{
- if (request.fHelp)
- masternode_list_conf_help();
-
- UniValue resultObj(UniValue::VOBJ);
-
- for (const auto& mne : masternodeConfig.getEntries()) {
- COutPoint outpoint = COutPoint(uint256S(mne.getTxHash()), (uint32_t)atoi(mne.getOutputIndex()));
- CMasternode mn;
- bool fFound = mnodeman.Get(outpoint, mn);
-
- std::string strStatus = fFound ? mn.GetStatus() : "MISSING";
-
- UniValue mnObj(UniValue::VOBJ);
- mnObj.push_back(Pair("alias", mne.getAlias()));
- mnObj.push_back(Pair("address", mne.getIp()));
- mnObj.push_back(Pair("privateKey", mne.getPrivKey()));
- mnObj.push_back(Pair("txHash", mne.getTxHash()));
- mnObj.push_back(Pair("outputIndex", mne.getOutputIndex()));
- mnObj.push_back(Pair("status", strStatus));
- resultObj.push_back(Pair("masternode", mnObj));
- }
-
- return resultObj;
-}
-
void masternode_status_help()
{
throw std::runtime_error(
@@ -662,26 +352,18 @@ UniValue masternode_status(const JSONRPCRequest& request)
mnObj.push_back(Pair("outpoint", activeMasternodeInfo.outpoint.ToStringShort()));
mnObj.push_back(Pair("service", activeMasternodeInfo.service.ToString()));
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
- auto dmn = activeMasternodeManager->GetDMN();
- if (dmn) {
- mnObj.push_back(Pair("proTxHash", dmn->proTxHash.ToString()));
- mnObj.push_back(Pair("collateralHash", dmn->collateralOutpoint.hash.ToString()));
- mnObj.push_back(Pair("collateralIndex", (int)dmn->collateralOutpoint.n));
- UniValue stateObj;
- dmn->pdmnState->ToJson(stateObj);
- mnObj.push_back(Pair("dmnState", stateObj));
- }
- mnObj.push_back(Pair("state", activeMasternodeManager->GetStateString()));
- mnObj.push_back(Pair("status", activeMasternodeManager->GetStatus()));
- } else {
- CMasternode mn;
- if (mnodeman.Get(activeMasternodeInfo.outpoint, mn)) {
- mnObj.push_back(Pair("payee", CBitcoinAddress(mn.keyIDCollateralAddress).ToString()));
- }
-
- mnObj.push_back(Pair("status", legacyActiveMasternodeManager.GetStatus()));
+ auto dmn = activeMasternodeManager->GetDMN();
+ if (dmn) {
+ mnObj.push_back(Pair("proTxHash", dmn->proTxHash.ToString()));
+ mnObj.push_back(Pair("collateralHash", dmn->collateralOutpoint.hash.ToString()));
+ mnObj.push_back(Pair("collateralIndex", (int)dmn->collateralOutpoint.n));
+ UniValue stateObj;
+ dmn->pdmnState->ToJson(stateObj);
+ mnObj.push_back(Pair("dmnState", stateObj));
}
+ mnObj.push_back(Pair("state", activeMasternodeManager->GetStateString()));
+ mnObj.push_back(Pair("status", activeMasternodeManager->GetStatus()));
+
return mnObj;
}
@@ -733,38 +415,6 @@ UniValue masternode_winners(const JSONRPCRequest& request)
return obj;
}
-void masternode_check_help()
-{
- throw std::runtime_error(
- "masternode check\n"
- "Force check all masternodes and remove invalid ones\n"
- );
-}
-
-UniValue masternode_check(const JSONRPCRequest& request)
-{
- if (request.fHelp)
- masternode_check_help();
-
- int countBeforeCheck = mnodeman.CountMasternodes();
- int countEnabledBeforeCheck = mnodeman.CountEnabled();
-
- mnodeman.CheckAndRemove(*g_connman);
-
- int countAfterCheck = mnodeman.CountMasternodes();
- int countEnabledAfterCheck = mnodeman.CountEnabled();
- int removedCount = std::max(0, countBeforeCheck - countAfterCheck);
- int removedEnabledCount = std::max(0, countEnabledBeforeCheck - countEnabledAfterCheck);
-
- UniValue obj(UniValue::VOBJ);
- obj.push_back(Pair("removedTotalCount", removedCount));
- obj.push_back(Pair("removedEnabledCount", removedEnabledCount));
- obj.push_back(Pair("totalCount", countAfterCheck));
- obj.push_back(Pair("enabledCount", countEnabledAfterCheck));
-
- return obj;
-}
-
[[ noreturn ]] void masternode_help()
{
throw std::runtime_error(
@@ -773,18 +423,13 @@ UniValue masternode_check(const JSONRPCRequest& request)
"\nArguments:\n"
"1. \"command\" (string or set of strings, required) The command to execute\n"
"\nAvailable commands:\n"
- " check - Force check all masternodes and remove invalid ones\n"
" count - Get information about number of masternodes (DEPRECATED options: 'total', 'ps', 'enabled', 'qualify', 'all')\n"
" current - Print info on current masternode winner to be paid the next block (calculated locally)\n"
- " genkey - Generate new masternodeprivkey, optional param: 'compressed' (boolean, optional, default=false) generate compressed privkey\n"
#ifdef ENABLE_WALLET
" outputs - Print masternode compatible outputs\n"
- " start-alias - Start single remote masternode by assigned alias configured in masternode.conf\n"
- " start- - Start remote masternodes configured in masternode.conf (: 'all', 'missing', 'disabled')\n"
#endif // ENABLE_WALLET
" status - Print masternode status information\n"
" list - Print list of all known masternodes (see masternodelist for more info)\n"
- " list-conf - Print masternode.conf in JSON format\n"
" winner - Print info on next masternode winner to vote for\n"
" winners - Print list of masternode winners\n"
);
@@ -816,20 +461,6 @@ UniValue masternode(const JSONRPCRequest& request)
return masternode_current(request);
} else if (strCommand == "winner") {
return masternode_winner(request);
-#ifdef ENABLE_WALLET
- } else if (strCommand == "start-alias") {
- return masternode_start_alias(request);
- } else if (strCommand == "start-all") {
- return masternode_start_all(request);
- } else if (strCommand == "start-missing") {
- return masternode_start_missing(request);
- } else if (strCommand == "start-disabled") {
- return masternode_start_disabled(request);
-#endif // ENABLE_WALLET
- } else if (strCommand == "genkey") {
- return masternode_genkey(request);
- } else if (strCommand == "list-conf") {
- return masternode_list_conf(request);
#ifdef ENABLE_WALLET
} else if (strCommand == "outputs") {
return masternode_outputs(request);
@@ -838,8 +469,6 @@ UniValue masternode(const JSONRPCRequest& request)
return masternode_status(request);
} else if (strCommand == "winners") {
return masternode_winners(request);
- } else if (strCommand == "check") {
- return masternode_check(request);
} else {
masternode_help();
}
@@ -854,430 +483,118 @@ UniValue masternodelist(const JSONRPCRequest& request)
if (request.params.size() == 2) strFilter = request.params[1].get_str();
if (request.fHelp || (
- strMode != "activeseconds" && strMode != "addr" && strMode != "daemon" && strMode != "full" && strMode != "info" && strMode != "json" &&
- strMode != "lastseen" && strMode != "lastpaidtime" && strMode != "lastpaidblock" &&
- strMode != "protocol" && strMode != "payee" && strMode != "pubkey" &&
- strMode != "rank" && strMode != "sentinel" && strMode != "status"))
+ strMode != "addr" && strMode != "full" && strMode != "info" && strMode != "json" &&
+ strMode != "lastpaidtime" && strMode != "lastpaidblock" &&
+ strMode != "payee" && strMode != "pubkey" &&
+ strMode != "status"))
{
masternode_list_help();
}
- if (strMode == "full" || strMode == "json" || strMode == "lastpaidtime" || strMode == "lastpaidblock") {
- CBlockIndex* pindex = NULL;
- {
- LOCK(cs_main);
- pindex = chainActive.Tip();
- }
- mnodeman.UpdateLastPaid(pindex);
- }
-
UniValue obj(UniValue::VOBJ);
- if (strMode == "rank") {
- CMasternodeMan::rank_pair_vec_t vMasternodeRanks;
- mnodeman.GetMasternodeRanks(vMasternodeRanks);
- for (const auto& rankpair : vMasternodeRanks) {
- std::string strOutpoint = rankpair.second.outpoint.ToStringShort();
- if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue;
- obj.push_back(Pair(strOutpoint, rankpair.first));
- }
- } else {
- std::map mapMasternodes = mnodeman.GetFullMasternodeMap();
- for (const auto& mnpair : mapMasternodes) {
- CMasternode mn = mnpair.second;
- std::string strOutpoint = mnpair.first.ToStringShort();
-
- CScript payeeScript;
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
- auto dmn = deterministicMNManager->GetListAtChainTip().GetMNByCollateral(mn.outpoint);
- if (dmn) {
- payeeScript = dmn->pdmnState->scriptPayout;
- }
- } else {
- payeeScript = GetScriptForDestination(mn.keyIDCollateralAddress);
- }
-
- CTxDestination payeeDest;
- std::string payeeStr = "UNKOWN";
- if (ExtractDestination(payeeScript, payeeDest)) {
- payeeStr = CBitcoinAddress(payeeDest).ToString();
- }
-
- if (strMode == "activeseconds") {
- if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue;
- obj.push_back(Pair(strOutpoint, (int64_t)(mn.lastPing.sigTime - mn.sigTime)));
- } else if (strMode == "addr") {
- std::string strAddress = mn.addr.ToString();
- if (strFilter !="" && strAddress.find(strFilter) == std::string::npos &&
- strOutpoint.find(strFilter) == std::string::npos) continue;
- obj.push_back(Pair(strOutpoint, strAddress));
- } else if (strMode == "daemon") {
- std::string strDaemon = mn.lastPing.GetDaemonString();
- if (strFilter !="" && strDaemon.find(strFilter) == std::string::npos &&
- strOutpoint.find(strFilter) == std::string::npos) continue;
- obj.push_back(Pair(strOutpoint, strDaemon));
- } else if (strMode == "sentinel") {
- std::string strSentinel = mn.lastPing.GetSentinelString();
- if (strFilter !="" && strSentinel.find(strFilter) == std::string::npos &&
- strOutpoint.find(strFilter) == std::string::npos) continue;
- obj.push_back(Pair(strOutpoint, strSentinel));
- } else if (strMode == "full") {
- std::ostringstream streamFull;
- streamFull << std::setw(18) <<
- mn.GetStatus() << " " <<
- mn.nProtocolVersion << " " <<
- payeeStr << " " <<
- (int64_t)mn.lastPing.sigTime << " " << std::setw(8) <<
- (int64_t)(mn.lastPing.sigTime - mn.sigTime) << " " << std::setw(10) <<
- mn.GetLastPaidTime() << " " << std::setw(6) <<
- mn.GetLastPaidBlock() << " " <<
- mn.addr.ToString();
- std::string strFull = streamFull.str();
- if (strFilter !="" && strFull.find(strFilter) == std::string::npos &&
- strOutpoint.find(strFilter) == std::string::npos) continue;
- obj.push_back(Pair(strOutpoint, strFull));
- } else if (strMode == "info") {
- std::ostringstream streamInfo;
- streamInfo << std::setw(18) <<
- mn.GetStatus() << " " <<
- mn.nProtocolVersion << " " <<
- payeeStr << " " <<
- (int64_t)mn.lastPing.sigTime << " " << std::setw(8) <<
- (int64_t)(mn.lastPing.sigTime - mn.sigTime) << " " <<
- mn.lastPing.GetSentinelString() << " " <<
- (mn.lastPing.fSentinelIsCurrent ? "current" : "expired") << " " <<
- mn.addr.ToString();
- std::string strInfo = streamInfo.str();
- if (strFilter !="" && strInfo.find(strFilter) == std::string::npos &&
- strOutpoint.find(strFilter) == std::string::npos) continue;
- obj.push_back(Pair(strOutpoint, strInfo));
- } else if (strMode == "json") {
- std::ostringstream streamInfo;
- streamInfo << mn.addr.ToString() << " " <<
- CBitcoinAddress(mn.pubKeyCollateralAddress.GetID()).ToString() << " " <<
- mn.GetStatus() << " " <<
- mn.nProtocolVersion << " " <<
- mn.lastPing.nDaemonVersion << " " <<
- mn.lastPing.GetSentinelString() << " " <<
- (mn.lastPing.fSentinelIsCurrent ? "current" : "expired") << " " <<
- (int64_t)mn.lastPing.sigTime << " " <<
- (int64_t)(mn.lastPing.sigTime - mn.sigTime) << " " <<
- mn.GetLastPaidTime() << " " <<
- mn.GetLastPaidBlock();
- std::string strInfo = streamInfo.str();
- if (strFilter !="" && strInfo.find(strFilter) == std::string::npos &&
- strOutpoint.find(strFilter) == std::string::npos) continue;
- UniValue objMN(UniValue::VOBJ);
- objMN.push_back(Pair("address", mn.addr.ToString()));
- objMN.push_back(Pair("payee", CBitcoinAddress(mn.pubKeyCollateralAddress.GetID()).ToString()));
- objMN.push_back(Pair("status", mn.GetStatus()));
- objMN.push_back(Pair("protocol", mn.nProtocolVersion));
- objMN.push_back(Pair("daemonversion", mn.lastPing.GetDaemonString()));
- objMN.push_back(Pair("sentinelversion", mn.lastPing.GetSentinelString()));
- objMN.push_back(Pair("sentinelstate", (mn.lastPing.fSentinelIsCurrent ? "current" : "expired")));
- objMN.push_back(Pair("lastseen", (int64_t)mn.lastPing.sigTime));
- objMN.push_back(Pair("activeseconds", (int64_t)(mn.lastPing.sigTime - mn.sigTime)));
- objMN.push_back(Pair("lastpaidtime", mn.GetLastPaidTime()));
- objMN.push_back(Pair("lastpaidblock", mn.GetLastPaidBlock()));
- obj.push_back(Pair(strOutpoint, objMN));
- } else if (strMode == "lastpaidblock") {
- if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue;
- obj.push_back(Pair(strOutpoint, mn.GetLastPaidBlock()));
- } else if (strMode == "lastpaidtime") {
- if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue;
- obj.push_back(Pair(strOutpoint, mn.GetLastPaidTime()));
- } else if (strMode == "lastseen") {
- if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue;
- obj.push_back(Pair(strOutpoint, (int64_t)mn.lastPing.sigTime));
- } else if (strMode == "payee") {
- if (strFilter !="" && payeeStr.find(strFilter) == std::string::npos &&
- strOutpoint.find(strFilter) == std::string::npos) continue;
- obj.push_back(Pair(strOutpoint, payeeStr));
- } else if (strMode == "protocol") {
- if (strFilter !="" && strFilter != strprintf("%d", mn.nProtocolVersion) &&
- strOutpoint.find(strFilter) == std::string::npos) continue;
- obj.push_back(Pair(strOutpoint, mn.nProtocolVersion));
- } else if (strMode == "keyIDOwner") {
- if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue;
- obj.push_back(Pair(strOutpoint, HexStr(mn.keyIDOwner)));
- } else if (strMode == "keyIDOperator") {
- if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue;
- obj.push_back(Pair(strOutpoint, HexStr(mn.legacyKeyIDOperator)));
- } else if (strMode == "keyIDVoting") {
- if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue;
- obj.push_back(Pair(strOutpoint, HexStr(mn.keyIDVoting)));
- } else if (strMode == "status") {
- std::string strStatus = mn.GetStatus();
- if (strFilter !="" && strStatus.find(strFilter) == std::string::npos &&
- strOutpoint.find(strFilter) == std::string::npos) continue;
- obj.push_back(Pair(strOutpoint, strStatus));
- }
- }
- }
- return obj;
-}
-
-bool DecodeHexVecMnb(std::vector& vecMnb, std::string strHexMnb) {
- if (!IsHex(strHexMnb))
- return false;
-
- std::vector mnbData(ParseHex(strHexMnb));
- CDataStream ssData(mnbData, SER_NETWORK, PROTOCOL_VERSION);
- try {
- ssData >> vecMnb;
- } catch (const std::exception&) {
- return false;
- }
-
- return true;
-}
-
-UniValue masternodebroadcast(const JSONRPCRequest& request)
-{
- std::string strCommand;
- if (request.params.size() >= 1)
- strCommand = request.params[0].get_str();
-
- if (request.fHelp ||
- (
-#ifdef ENABLE_WALLET
- strCommand != "create-alias" && strCommand != "create-all" &&
-#endif // ENABLE_WALLET
- strCommand != "decode" && strCommand != "relay"))
- throw std::runtime_error(
- "masternodebroadcast \"command\"...\n"
- "Set of commands to create and relay masternode broadcast messages\n"
- "\nArguments:\n"
- "1. \"command\" (string or set of strings, required) The command to execute\n"
- "\nAvailable commands:\n"
-#ifdef ENABLE_WALLET
- " create-alias - Create single remote masternode broadcast message by assigned alias configured in masternode.conf\n"
- " create-all - Create remote masternode broadcast messages for all masternodes configured in masternode.conf\n"
-#endif // ENABLE_WALLET
- " decode - Decode masternode broadcast message\n"
- " relay - Relay masternode broadcast message to the network\n"
- );
-
-#ifdef ENABLE_WALLET
- if (strCommand == "create-alias") {
- if (!EnsureWalletIsAvailable(request.fHelp))
- return NullUniValue;
-
- // wait for reindex and/or import to finish
- if (fImporting || fReindex)
- throw JSONRPCError(RPC_INTERNAL_ERROR, "Wait for reindex and/or import to finish");
-
- if (request.params.size() < 2)
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Please specify an alias");
-
- {
- LOCK(pwalletMain->cs_wallet);
- EnsureWalletIsUnlocked();
+ auto mnList = deterministicMNManager->GetListAtChainTip();
+ auto dmnToStatus = [&](const CDeterministicMNCPtr& dmn) {
+ if (mnList.IsMNValid(dmn)) {
+ return "ENABLED";
}
-
- bool fFound = false;
- std::string strAlias = request.params[1].get_str();
-
- UniValue statusObj(UniValue::VOBJ);
- std::vector vecMnb;
-
- statusObj.push_back(Pair("alias", strAlias));
-
- for (const auto& mne : masternodeConfig.getEntries()) {
- if (mne.getAlias() == strAlias) {
- fFound = true;
- std::string strError;
- CMasternodeBroadcast mnb;
-
- bool fResult = CMasternodeBroadcast::Create(mne.getIp(), mne.getPrivKey(), mne.getTxHash(), mne.getOutputIndex(), strError, mnb, true);
-
- statusObj.push_back(Pair("result", fResult ? "successful" : "failed"));
- if (fResult) {
- vecMnb.push_back(mnb);
- CDataStream ssVecMnb(SER_NETWORK, PROTOCOL_VERSION);
- ssVecMnb << vecMnb;
- statusObj.push_back(Pair("hex", HexStr(ssVecMnb)));
- } else {
- statusObj.push_back(Pair("errorMessage", strError));
- }
- break;
- }
+ if (mnList.IsMNPoSeBanned(dmn)) {
+ return "POSE_BANNED";
}
-
- if (!fFound) {
- statusObj.push_back(Pair("result", "not found"));
- statusObj.push_back(Pair("errorMessage", "Could not find alias in config. Verify with list-conf."));
+ return "UNKNOWN";
+ };
+ auto dmnToLastPaidTime = [&](const CDeterministicMNCPtr& dmn) {
+ if (dmn->pdmnState->nLastPaidHeight == 0) {
+ return (int)0;
}
- return statusObj;
-
- }
-
- if (strCommand == "create-all") {
- if (!EnsureWalletIsAvailable(request.fHelp))
- return NullUniValue;
-
- // wait for reindex and/or import to finish
- if (fImporting || fReindex)
- throw JSONRPCError(RPC_INTERNAL_ERROR, "Wait for reindex and/or import to finish");
-
- {
- LOCK(pwalletMain->cs_wallet);
- EnsureWalletIsUnlocked();
- }
-
- int nSuccessful = 0;
- int nFailed = 0;
-
- UniValue resultsObj(UniValue::VOBJ);
- std::vector vecMnb;
-
- for (const auto& mne : masternodeConfig.getEntries()) {
- std::string strError;
- CMasternodeBroadcast mnb;
-
- bool fResult = CMasternodeBroadcast::Create(mne.getIp(), mne.getPrivKey(), mne.getTxHash(), mne.getOutputIndex(), strError, mnb, true);
-
- UniValue statusObj(UniValue::VOBJ);
- statusObj.push_back(Pair("alias", mne.getAlias()));
- statusObj.push_back(Pair("result", fResult ? "successful" : "failed"));
-
- if (fResult) {
- nSuccessful++;
- vecMnb.push_back(mnb);
- } else {
- nFailed++;
- statusObj.push_back(Pair("errorMessage", strError));
- }
-
- resultsObj.push_back(Pair("status", statusObj));
- }
-
- CDataStream ssVecMnb(SER_NETWORK, PROTOCOL_VERSION);
- ssVecMnb << vecMnb;
- UniValue returnObj(UniValue::VOBJ);
- returnObj.push_back(Pair("overall", strprintf("Successfully created broadcast messages for %d masternodes, failed to create %d, total %d", nSuccessful, nFailed, nSuccessful + nFailed)));
- returnObj.push_back(Pair("detail", resultsObj));
- returnObj.push_back(Pair("hex", HexStr(ssVecMnb.begin(), ssVecMnb.end())));
-
- return returnObj;
- }
-#endif // ENABLE_WALLET
-
- if (strCommand == "decode") {
- if (request.params.size() != 2)
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Correct usage is 'masternodebroadcast decode \"hexstring\"'");
-
- std::vector vecMnb;
-
- if (!DecodeHexVecMnb(vecMnb, request.params[1].get_str()))
- throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Masternode broadcast message decode failed");
-
- int nSuccessful = 0;
- int nFailed = 0;
- int nDos = 0;
- UniValue returnObj(UniValue::VOBJ);
-
- for (const auto& mnb : vecMnb) {
- UniValue resultObj(UniValue::VOBJ);
-
- if (mnb.CheckSignature(nDos)) {
- nSuccessful++;
- resultObj.push_back(Pair("outpoint", mnb.outpoint.ToStringShort()));
- resultObj.push_back(Pair("addr", mnb.addr.ToString()));
- resultObj.push_back(Pair("keyIDCollateralAddress", CBitcoinAddress(mnb.keyIDCollateralAddress).ToString()));
- resultObj.push_back(Pair("keyIDMasternode", CBitcoinAddress(mnb.legacyKeyIDOperator).ToString()));
- resultObj.push_back(Pair("vchSig", EncodeBase64(&mnb.vchSig[0], mnb.vchSig.size())));
- resultObj.push_back(Pair("sigTime", mnb.sigTime));
- resultObj.push_back(Pair("protocolVersion", mnb.nProtocolVersion));
- resultObj.push_back(Pair("nLastDsq", mnb.nLastDsq));
-
- UniValue lastPingObj(UniValue::VOBJ);
- lastPingObj.push_back(Pair("outpoint", mnb.lastPing.masternodeOutpoint.ToStringShort()));
- lastPingObj.push_back(Pair("blockHash", mnb.lastPing.blockHash.ToString()));
- lastPingObj.push_back(Pair("sigTime", mnb.lastPing.sigTime));
- lastPingObj.push_back(Pair("vchSig", EncodeBase64(&mnb.lastPing.vchSig[0], mnb.lastPing.vchSig.size())));
-
- resultObj.push_back(Pair("lastPing", lastPingObj));
- } else {
- nFailed++;
- resultObj.push_back(Pair("errorMessage", "Masternode broadcast signature verification failed"));
- }
-
- returnObj.push_back(Pair(mnb.GetHash().ToString(), resultObj));
+ LOCK(cs_main);
+ const CBlockIndex* pindex = chainActive[dmn->pdmnState->nLastPaidHeight];
+ return (int)pindex->nTime;
+ };
+
+ mnList.ForEachMN(false, [&](const CDeterministicMNCPtr& dmn) {
+ std::string strOutpoint = dmn->collateralOutpoint.ToStringShort();
+
+ CScript payeeScript = dmn->pdmnState->scriptPayout;
+ CTxDestination payeeDest;
+ std::string payeeStr = "UNKOWN";
+ if (ExtractDestination(payeeScript, payeeDest)) {
+ payeeStr = CBitcoinAddress(payeeDest).ToString();
}
- returnObj.push_back(Pair("overall", strprintf("Successfully decoded broadcast messages for %d masternodes, failed to decode %d, total %d", nSuccessful, nFailed, nSuccessful + nFailed)));
-
- return returnObj;
- }
-
- if (strCommand == "relay") {
- if (request.params.size() < 2 || request.params.size() > 3)
- throw JSONRPCError(RPC_INVALID_PARAMETER, "masternodebroadcast relay \"hexstring\"\n"
- "\nArguments:\n"
- "1. \"hex\" (string, required) Broadcast messages hex string\n");
-
- std::vector vecMnb;
-
- if (!DecodeHexVecMnb(vecMnb, request.params[1].get_str()))
- throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Masternode broadcast message decode failed");
-
- int nSuccessful = 0;
- int nFailed = 0;
- UniValue returnObj(UniValue::VOBJ);
-
- // verify all signatures first, bailout if any of them broken
- for (const auto& mnb : vecMnb) {
- UniValue resultObj(UniValue::VOBJ);
-
- resultObj.push_back(Pair("outpoint", mnb.outpoint.ToStringShort()));
- resultObj.push_back(Pair("addr", mnb.addr.ToString()));
-
- int nDos = 0;
- bool fResult;
- if (mnb.CheckSignature(nDos)) {
- fResult = mnodeman.CheckMnbAndUpdateMasternodeList(NULL, mnb, nDos, *g_connman);
- mnodeman.NotifyMasternodeUpdates(*g_connman);
- } else fResult = false;
-
- if (fResult) {
- nSuccessful++;
- resultObj.push_back(Pair(mnb.GetHash().ToString(), "successful"));
- } else {
- nFailed++;
- resultObj.push_back(Pair("errorMessage", "Masternode broadcast signature verification failed"));
- }
-
- returnObj.push_back(Pair(mnb.GetHash().ToString(), resultObj));
+ if (strMode == "addr") {
+ std::string strAddress = dmn->pdmnState->ToString();
+ if (strFilter !="" && strAddress.find(strFilter) == std::string::npos &&
+ strOutpoint.find(strFilter) == std::string::npos) return;
+ obj.push_back(Pair(strOutpoint, strAddress));
+ } else if (strMode == "full") {
+ std::ostringstream streamFull;
+ streamFull << std::setw(18) <<
+ dmnToStatus(dmn) << " " <<
+ payeeStr << " " <<
+ dmnToLastPaidTime(dmn) << " " << std::setw(6) <<
+ dmn->pdmnState->nLastPaidHeight << " " <<
+ dmn->pdmnState->addr.ToString();
+ std::string strFull = streamFull.str();
+ if (strFilter !="" && strFull.find(strFilter) == std::string::npos &&
+ strOutpoint.find(strFilter) == std::string::npos) return;
+ obj.push_back(Pair(strOutpoint, strFull));
+ } else if (strMode == "info") {
+ std::ostringstream streamInfo;
+ streamInfo << std::setw(18) <<
+ dmnToStatus(dmn) << " " <<
+ payeeStr << " " <<
+ dmn->pdmnState->addr.ToString();
+ std::string strInfo = streamInfo.str();
+ if (strFilter !="" && strInfo.find(strFilter) == std::string::npos &&
+ strOutpoint.find(strFilter) == std::string::npos) return;
+ obj.push_back(Pair(strOutpoint, strInfo));
+ } else if (strMode == "json") {
+ std::ostringstream streamInfo;
+ streamInfo << dmn->pdmnState->addr.ToString() << " " <<
+ CBitcoinAddress(dmn->pdmnState->scriptPayout).ToString() << " " <<
+ dmnToStatus(dmn) << " " <<
+ dmnToLastPaidTime(dmn) << " " <<
+ dmn->pdmnState->nLastPaidHeight;
+ std::string strInfo = streamInfo.str();
+ if (strFilter !="" && strInfo.find(strFilter) == std::string::npos &&
+ strOutpoint.find(strFilter) == std::string::npos) return;
+ UniValue objMN(UniValue::VOBJ);
+ objMN.push_back(Pair("address", dmn->pdmnState->addr.ToString()));
+ objMN.push_back(Pair("payee", CBitcoinAddress(dmn->pdmnState->scriptPayout).ToString()));
+ objMN.push_back(Pair("status", dmnToStatus(dmn)));
+ objMN.push_back(Pair("lastpaidtime", dmnToLastPaidTime(dmn)));
+ objMN.push_back(Pair("lastpaidblock", dmn->pdmnState->nLastPaidHeight));
+ obj.push_back(Pair(strOutpoint, objMN));
+ } else if (strMode == "lastpaidblock") {
+ if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) return;
+ obj.push_back(Pair(strOutpoint, dmn->pdmnState->nLastPaidHeight));
+ } else if (strMode == "lastpaidtime") {
+ if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) return;
+ obj.push_back(Pair(strOutpoint, dmnToLastPaidTime(dmn)));
+ } else if (strMode == "payee") {
+ if (strFilter !="" && payeeStr.find(strFilter) == std::string::npos &&
+ strOutpoint.find(strFilter) == std::string::npos) return;
+ obj.push_back(Pair(strOutpoint, payeeStr));
+ } else if (strMode == "keyIDOwner") {
+ if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) return;
+ obj.push_back(Pair(strOutpoint, HexStr(dmn->pdmnState->keyIDOwner)));
+ } else if (strMode == "pubKeyOperator") {
+ if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) return;
+ obj.push_back(Pair(strOutpoint, dmn->pdmnState->pubKeyOperator.ToString()));
+ } else if (strMode == "keyIDVoting") {
+ if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) return;
+ obj.push_back(Pair(strOutpoint, HexStr(dmn->pdmnState->keyIDVoting)));
+ } else if (strMode == "status") {
+ std::string strStatus = dmnToStatus(dmn);
+ if (strFilter !="" && strStatus.find(strFilter) == std::string::npos &&
+ strOutpoint.find(strFilter) == std::string::npos) return;
+ obj.push_back(Pair(strOutpoint, strStatus));
}
+ });
- returnObj.push_back(Pair("overall", strprintf("Successfully relayed broadcast messages for %d masternodes, failed to relay %d, total %d", nSuccessful, nFailed, nSuccessful + nFailed)));
-
- return returnObj;
- }
-
- return NullUniValue;
-}
-
-UniValue sentinelping(const JSONRPCRequest& request)
-{
- if (request.fHelp || request.params.size() != 1) {
- throw std::runtime_error(
- "sentinelping version\n"
- "\nSentinel ping.\n"
- "\nArguments:\n"
- "1. version (string, required) Sentinel version in the form \"x.x.x\"\n"
- "\nResult:\n"
- "state (boolean) Ping result\n"
- "\nExamples:\n"
- + HelpExampleCli("sentinelping", "1.0.2")
- + HelpExampleRpc("sentinelping", "1.0.2")
- );
- }
-
- legacyActiveMasternodeManager.UpdateSentinelPing(StringVersionToInt(request.params[0].get_str()));
- return true;
+ return obj;
}
static const CRPCCommand commands[] =
@@ -1285,9 +602,7 @@ static const CRPCCommand commands[] =
// --------------------- ------------------------ ----------------------- ------ ----------
{ "dash", "masternode", &masternode, true, {} },
{ "dash", "masternodelist", &masternodelist, true, {} },
- { "dash", "masternodebroadcast", &masternodebroadcast, true, {} },
{ "dash", "getpoolinfo", &getpoolinfo, true, {} },
- { "dash", "sentinelping", &sentinelping, true, {} },
#ifdef ENABLE_WALLET
{ "dash", "privatesend", &privatesend, false, {} },
#endif // ENABLE_WALLET
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index 43522360d6d5..0bfe88a8f0e5 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -497,12 +497,10 @@ UniValue getblocktemplate(const JSONRPCRequest& request)
throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Dash Core is downloading blocks...");
}
- // when enforcement is on we need information about a masternode payee or otherwise our block is going to be orphaned by the network
+ // Get expected MN/superblock payees. The call to GetBlockTxOuts might fail on regtest/devnet or when
+ // testnet is reset. This is fine and we ignore failure (blocks will be accepted)
std::vector voutMasternodePayments;
- if (sporkManager.IsSporkActive(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT)
- && !masternodeSync.IsWinnersListSynced()
- && !mnpayments.GetBlockTxOuts(chainActive.Height() + 1, 0, voutMasternodePayments))
- throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Dash Core is downloading masternode winners...");
+ mnpayments.GetBlockTxOuts(chainActive.Height() + 1, 0, voutMasternodePayments);
// next bock is a superblock and we need governance info to correctly construct it
if (sporkManager.IsSporkActive(SPORK_9_SUPERBLOCKS_ENABLED)
@@ -722,7 +720,7 @@ UniValue getblocktemplate(const JSONRPCRequest& request)
result.push_back(Pair("masternode", masternodeObj));
result.push_back(Pair("masternode_payments_started", pindexPrev->nHeight + 1 > consensusParams.nMasternodePaymentsStartBlock));
- result.push_back(Pair("masternode_payments_enforced", deterministicMNManager->IsDeterministicMNsSporkActive() || sporkManager.IsSporkActive(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT)));
+ result.push_back(Pair("masternode_payments_enforced", true));
UniValue superblockObjArray(UniValue::VARR);
if(pblocktemplate->voutSuperblockPayments.size()) {
diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp
index 1c321b6ca046..8799a7959f06 100644
--- a/src/rpc/misc.cpp
+++ b/src/rpc/misc.cpp
@@ -157,8 +157,6 @@ UniValue mnsync(const JSONRPCRequest& request)
objStatus.push_back(Pair("AssetStartTime", masternodeSync.GetAssetStartTime()));
objStatus.push_back(Pair("Attempt", masternodeSync.GetAttempt()));
objStatus.push_back(Pair("IsBlockchainSynced", masternodeSync.IsBlockchainSynced()));
- objStatus.push_back(Pair("IsMasternodeListSynced", masternodeSync.IsMasternodeListSynced()));
- objStatus.push_back(Pair("IsWinnersListSynced", masternodeSync.IsWinnersListSynced()));
objStatus.push_back(Pair("IsSynced", masternodeSync.IsSynced()));
objStatus.push_back(Pair("IsFailed", masternodeSync.IsFailed()));
return objStatus;
diff --git a/src/serialize.h b/src/serialize.h
index 37ffac5b7f8d..f87009855a2a 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -596,8 +596,8 @@ template void Unserializ
/**
* shared_ptr
*/
-template void Serialize(Stream& os, const std::shared_ptr& p);
-template void Unserialize(Stream& os, std::shared_ptr& p);
+template void Serialize(Stream& os, const std::shared_ptr& p);
+template void Unserialize(Stream& os, std::shared_ptr& p);
/**
* unique_ptr
@@ -941,15 +941,15 @@ void Unserialize(Stream& is, std::unique_ptr& p)
* shared_ptr
*/
template void
-Serialize(Stream& os, const std::shared_ptr& p)
+Serialize(Stream& os, const std::shared_ptr& p)
{
Serialize(os, *p);
}
template
-void Unserialize(Stream& is, std::shared_ptr& p)
+void Unserialize(Stream& is, std::shared_ptr& p)
{
- p = std::make_shared(deserialize, is);
+ p = std::make_shared(deserialize, is);
}
diff --git a/src/spork.cpp b/src/spork.cpp
index d2e1cd678e39..841b78a1ecd3 100644
--- a/src/spork.cpp
+++ b/src/spork.cpp
@@ -21,13 +21,8 @@ std::map mapSporkDefaults = {
{SPORK_2_INSTANTSEND_ENABLED, 0}, // ON
{SPORK_3_INSTANTSEND_BLOCK_FILTERING, 0}, // ON
{SPORK_5_INSTANTSEND_MAX_VALUE, 1000}, // 1000 Dash
- {SPORK_6_NEW_SIGS, 4070908800ULL}, // OFF
- {SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT, 4070908800ULL}, // OFF
{SPORK_9_SUPERBLOCKS_ENABLED, 4070908800ULL}, // OFF
- {SPORK_10_MASTERNODE_PAY_UPDATED_NODES, 4070908800ULL}, // OFF
{SPORK_12_RECONSIDER_BLOCKS, 0}, // 0 BLOCKS
- {SPORK_14_REQUIRE_SENTINEL_FLAG, 4070908800ULL}, // OFF
- {SPORK_15_DETERMINISTIC_MNS_ENABLED, 4070908800ULL}, // OFF
{SPORK_16_INSTANTSEND_AUTOLOCKS, 4070908800ULL}, // OFF
{SPORK_17_QUORUM_DKG_ENABLED, 4070908800ULL}, // OFF
};
@@ -76,12 +71,10 @@ void CSporkManager::CheckAndRemove()
mapSporksByHash.erase(itSignerPair->second.GetHash());
continue;
}
- if (!itSignerPair->second.CheckSignature(itSignerPair->first, false)) {
- if (!itSignerPair->second.CheckSignature(itSignerPair->first, true)) {
- mapSporksByHash.erase(itSignerPair->second.GetHash());
- itActive->second.erase(itSignerPair++);
- continue;
- }
+ if (!itSignerPair->second.CheckSignature(itSignerPair->first)) {
+ mapSporksByHash.erase(itSignerPair->second.GetHash());
+ itActive->second.erase(itSignerPair++);
+ continue;
}
++itSignerPair;
}
@@ -96,8 +89,7 @@ void CSporkManager::CheckAndRemove()
while (itByHash != mapSporksByHash.end()) {
bool found = false;
for (const auto& signer: setSporkPubKeyIDs) {
- if (itByHash->second.CheckSignature(signer, false) ||
- itByHash->second.CheckSignature(signer, true)) {
+ if (itByHash->second.CheckSignature(signer)) {
found = true;
break;
}
@@ -130,19 +122,11 @@ void CSporkManager::ProcessSpork(CNode* pfrom, const std::string& strCommand, CD
}
CKeyID keyIDSigner;
- bool fSpork6IsActive = IsSporkActive(SPORK_6_NEW_SIGS);
- if (!spork.GetSignerKeyID(keyIDSigner, fSpork6IsActive)
- || !setSporkPubKeyIDs.count(keyIDSigner)) {
- // Note: unlike for other messages we have to check for new format even with SPORK_6_NEW_SIGS
- // inactive because SPORK_6_NEW_SIGS default is OFF and it is not the first spork to sync
- // (and even if it would, spork order can't be guaranteed anyway).
- if (!spork.GetSignerKeyID(keyIDSigner, !fSpork6IsActive)
- || !setSporkPubKeyIDs.count(keyIDSigner)) {
- LOCK(cs_main);
- LogPrintf("CSporkManager::ProcessSpork -- ERROR: invalid signature\n");
- Misbehaving(pfrom->GetId(), 100);
- return;
- }
+ if (!spork.GetSignerKeyID(keyIDSigner) || !setSporkPubKeyIDs.count(keyIDSigner)) {
+ LOCK(cs_main);
+ LogPrintf("CSporkManager::ProcessSpork -- ERROR: invalid signature\n");
+ Misbehaving(pfrom->GetId(), 100);
+ return;
}
{
@@ -221,10 +205,9 @@ bool CSporkManager::UpdateSpork(int nSporkID, int64_t nValue, CConnman& connman)
{
CSporkMessage spork = CSporkMessage(nSporkID, nValue, GetAdjustedTime());
- bool fSpork6IsActive = IsSporkActive(SPORK_6_NEW_SIGS);
- if(spork.Sign(sporkPrivKey, fSpork6IsActive)) {
+ if(spork.Sign(sporkPrivKey)) {
CKeyID keyIDSigner;
- if (!spork.GetSignerKeyID(keyIDSigner, fSpork6IsActive) || !setSporkPubKeyIDs.count(keyIDSigner)) {
+ if (!spork.GetSignerKeyID(keyIDSigner) || !setSporkPubKeyIDs.count(keyIDSigner)) {
LogPrintf("CSporkManager::UpdateSpork: failed to find keyid for private key\n");
return false;
}
@@ -277,13 +260,8 @@ int CSporkManager::GetSporkIDByName(const std::string& strName)
if (strName == "SPORK_2_INSTANTSEND_ENABLED") return SPORK_2_INSTANTSEND_ENABLED;
if (strName == "SPORK_3_INSTANTSEND_BLOCK_FILTERING") return SPORK_3_INSTANTSEND_BLOCK_FILTERING;
if (strName == "SPORK_5_INSTANTSEND_MAX_VALUE") return SPORK_5_INSTANTSEND_MAX_VALUE;
- if (strName == "SPORK_6_NEW_SIGS") return SPORK_6_NEW_SIGS;
- if (strName == "SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT") return SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT;
if (strName == "SPORK_9_SUPERBLOCKS_ENABLED") return SPORK_9_SUPERBLOCKS_ENABLED;
- if (strName == "SPORK_10_MASTERNODE_PAY_UPDATED_NODES") return SPORK_10_MASTERNODE_PAY_UPDATED_NODES;
if (strName == "SPORK_12_RECONSIDER_BLOCKS") return SPORK_12_RECONSIDER_BLOCKS;
- if (strName == "SPORK_14_REQUIRE_SENTINEL_FLAG") return SPORK_14_REQUIRE_SENTINEL_FLAG;
- if (strName == "SPORK_15_DETERMINISTIC_MNS_ENABLED") return SPORK_15_DETERMINISTIC_MNS_ENABLED;
if (strName == "SPORK_16_INSTANTSEND_AUTOLOCKS") return SPORK_16_INSTANTSEND_AUTOLOCKS;
if (strName == "SPORK_17_QUORUM_DKG_ENABLED") return SPORK_17_QUORUM_DKG_ENABLED;
@@ -297,13 +275,8 @@ std::string CSporkManager::GetSporkNameByID(int nSporkID)
case SPORK_2_INSTANTSEND_ENABLED: return "SPORK_2_INSTANTSEND_ENABLED";
case SPORK_3_INSTANTSEND_BLOCK_FILTERING: return "SPORK_3_INSTANTSEND_BLOCK_FILTERING";
case SPORK_5_INSTANTSEND_MAX_VALUE: return "SPORK_5_INSTANTSEND_MAX_VALUE";
- case SPORK_6_NEW_SIGS: return "SPORK_6_NEW_SIGS";
- case SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT: return "SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT";
case SPORK_9_SUPERBLOCKS_ENABLED: return "SPORK_9_SUPERBLOCKS_ENABLED";
- case SPORK_10_MASTERNODE_PAY_UPDATED_NODES: return "SPORK_10_MASTERNODE_PAY_UPDATED_NODES";
case SPORK_12_RECONSIDER_BLOCKS: return "SPORK_12_RECONSIDER_BLOCKS";
- case SPORK_14_REQUIRE_SENTINEL_FLAG: return "SPORK_14_REQUIRE_SENTINEL_FLAG";
- case SPORK_15_DETERMINISTIC_MNS_ENABLED: return "SPORK_15_DETERMINISTIC_MNS_ENABLED";
case SPORK_16_INSTANTSEND_AUTOLOCKS: return "SPORK_16_INSTANTSEND_AUTOLOCKS";
case SPORK_17_QUORUM_DKG_ENABLED: return "SPORK_17_QUORUM_DKG_ENABLED";
default:
@@ -364,7 +337,7 @@ bool CSporkManager::SetPrivKey(const std::string& strPrivKey)
}
CSporkMessage spork;
- if (spork.Sign(key, IsSporkActive(SPORK_6_NEW_SIGS))) {
+ if (spork.Sign(key)) {
LOCK(cs);
// Test signing successful, proceed
LogPrintf("CSporkManager::SetPrivKey -- Successfully initialized as spork signer\n");
@@ -397,7 +370,7 @@ uint256 CSporkMessage::GetSignatureHash() const
return s.GetHash();
}
-bool CSporkMessage::Sign(const CKey& key, bool fSporkSixActive)
+bool CSporkMessage::Sign(const CKey& key)
{
if (!key.IsValid()) {
LogPrintf("CSporkMessage::Sign -- signing key is not valid\n");
@@ -407,81 +380,40 @@ bool CSporkMessage::Sign(const CKey& key, bool fSporkSixActive)
CKeyID pubKeyId = key.GetPubKey().GetID();
std::string strError = "";
- if (fSporkSixActive) {
- uint256 hash = GetSignatureHash();
+ uint256 hash = GetSignatureHash();
- if(!CHashSigner::SignHash(hash, key, vchSig)) {
- LogPrintf("CSporkMessage::Sign -- SignHash() failed\n");
- return false;
- }
-
- if (!CHashSigner::VerifyHash(hash, pubKeyId, vchSig, strError)) {
- LogPrintf("CSporkMessage::Sign -- VerifyHash() failed, error: %s\n", strError);
- return false;
- }
- } else {
- std::string strMessage = std::to_string(nSporkID) + std::to_string(nValue) + std::to_string(nTimeSigned);
-
- if(!CMessageSigner::SignMessage(strMessage, vchSig, key)) {
- LogPrintf("CSporkMessage::Sign -- SignMessage() failed\n");
- return false;
- }
+ if(!CHashSigner::SignHash(hash, key, vchSig)) {
+ LogPrintf("CSporkMessage::Sign -- SignHash() failed\n");
+ return false;
+ }
- if(!CMessageSigner::VerifyMessage(pubKeyId, vchSig, strMessage, strError)) {
- LogPrintf("CSporkMessage::Sign -- VerifyMessage() failed, error: %s\n", strError);
- return false;
- }
+ if (!CHashSigner::VerifyHash(hash, pubKeyId, vchSig, strError)) {
+ LogPrintf("CSporkMessage::Sign -- VerifyHash() failed, error: %s\n", strError);
+ return false;
}
return true;
}
-bool CSporkMessage::CheckSignature(const CKeyID& pubKeyId, bool fSporkSixActive) const
+bool CSporkMessage::CheckSignature(const CKeyID& pubKeyId) const
{
std::string strError = "";
- if (fSporkSixActive) {
uint256 hash = GetSignatureHash();
- if (!CHashSigner::VerifyHash(hash, pubKeyId, vchSig, strError)) {
- // Note: unlike for many other messages when SPORK_6_NEW_SIGS is ON sporks with sigs in old format
- // and newer timestamps should not be accepted, so if we failed here - that's it
- LogPrintf("CSporkMessage::CheckSignature -- VerifyHash() failed, error: %s\n", strError);
- return false;
- }
- } else {
- std::string strMessage = std::to_string(nSporkID) + std::to_string(nValue) + std::to_string(nTimeSigned);
-
- if (!CMessageSigner::VerifyMessage(pubKeyId, vchSig, strMessage, strError)){
- // Note: unlike for other messages we have to check for new format even with SPORK_6_NEW_SIGS
- // inactive because SPORK_6_NEW_SIGS default is OFF and it is not the first spork to sync
- // (and even if it would, spork order can't be guaranteed anyway).
- uint256 hash = GetSignatureHash();
- if (!CHashSigner::VerifyHash(hash, pubKeyId, vchSig, strError)) {
- LogPrintf("CSporkMessage::CheckSignature -- VerifyHash() failed, error: %s\n", strError);
- return false;
- }
- }
+ if (!CHashSigner::VerifyHash(hash, pubKeyId, vchSig, strError)) {
+ LogPrintf("CSporkMessage::CheckSignature -- VerifyHash() failed, error: %s\n", strError);
+ return false;
}
return true;
}
-bool CSporkMessage::GetSignerKeyID(CKeyID &retKeyidSporkSigner, bool fSporkSixActive)
+bool CSporkMessage::GetSignerKeyID(CKeyID &retKeyidSporkSigner)
{
CPubKey pubkeyFromSig;
- if (fSporkSixActive) {
- if (!pubkeyFromSig.RecoverCompact(GetSignatureHash(), vchSig)) {
- return false;
- }
- } else {
- std::string strMessage = std::to_string(nSporkID) + std::to_string(nValue) + std::to_string(nTimeSigned);
- CHashWriter ss(SER_GETHASH, 0);
- ss << strMessageMagic;
- ss << strMessage;
- if (!pubkeyFromSig.RecoverCompact(ss.GetHash(), vchSig)) {
- return false;
- }
+ if (!pubkeyFromSig.RecoverCompact(GetSignatureHash(), vchSig)) {
+ return false;
}
retKeyidSporkSigner = pubkeyFromSig.GetID();
diff --git a/src/spork.h b/src/spork.h
index f2baecf6a19b..ec86f37d8132 100644
--- a/src/spork.h
+++ b/src/spork.h
@@ -20,13 +20,8 @@ class CSporkManager;
static const int SPORK_2_INSTANTSEND_ENABLED = 10001;
static const int SPORK_3_INSTANTSEND_BLOCK_FILTERING = 10002;
static const int SPORK_5_INSTANTSEND_MAX_VALUE = 10004;
-static const int SPORK_6_NEW_SIGS = 10005;
-static const int SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT = 10007;
static const int SPORK_9_SUPERBLOCKS_ENABLED = 10008;
-static const int SPORK_10_MASTERNODE_PAY_UPDATED_NODES = 10009;
static const int SPORK_12_RECONSIDER_BLOCKS = 10011;
-static const int SPORK_14_REQUIRE_SENTINEL_FLAG = 10013;
-static const int SPORK_15_DETERMINISTIC_MNS_ENABLED = 10014;
static const int SPORK_16_INSTANTSEND_AUTOLOCKS = 10015;
static const int SPORK_17_QUORUM_DKG_ENABLED = 10016;
@@ -102,13 +97,13 @@ class CSporkMessage
/**
* Sign will sign the spork message with the given key.
*/
- bool Sign(const CKey& key, bool fSporkSixActive);
+ bool Sign(const CKey& key);
/**
* CheckSignature will ensure the spork signature matches the provided public
* key hash.
*/
- bool CheckSignature(const CKeyID& pubKeyId, bool fSporkSixActive) const;
+ bool CheckSignature(const CKeyID& pubKeyId) const;
/**
* GetSignerKeyID is used to recover the spork address of the key used to
@@ -117,7 +112,7 @@ class CSporkMessage
* This method was introduced along with the multi-signer sporks feature,
* in order to identify which spork key signed this message.
*/
- bool GetSignerKeyID(CKeyID& retKeyidSporkSigner, bool fSporkSixActive);
+ bool GetSignerKeyID(CKeyID& retKeyidSporkSigner);
/**
* Relay is used to send this spork message to other peers.
diff --git a/src/test/evo_deterministicmns_tests.cpp b/src/test/evo_deterministicmns_tests.cpp
index ca0eb0bcd0e1..6fb85b89baed 100644
--- a/src/test/evo_deterministicmns_tests.cpp
+++ b/src/test/evo_deterministicmns_tests.cpp
@@ -279,8 +279,6 @@ BOOST_FIXTURE_TEST_CASE(dip3_protx, TestChainDIP3Setup)
nHeight++;
}
- // activate spork15
- sporkManager.UpdateSpork(SPORK_15_DETERMINISTIC_MNS_ENABLED, chainActive.Height() + 1, *g_connman);
CreateAndProcessBlock({}, coinbaseKey);
deterministicMNManager->UpdatedBlockTip(chainActive.Tip());
nHeight++;
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index 2cfe0da15224..e8d309f1607a 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -205,9 +205,6 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
LOCK(cs_main);
fCheckpointsEnabled = false;
- // force UpdatedBlockTip to initialize nCachedBlockHeight
- mnpayments.UpdatedBlockTip(chainActive.Tip(), *connman);
-
// Simple block creation, nothing special yet:
BOOST_CHECK(pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey));
diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp
index 5b99cec5582f..8c00487925c7 100644
--- a/src/test/rpc_tests.cpp
+++ b/src/test/rpc_tests.cpp
@@ -343,11 +343,4 @@ BOOST_AUTO_TEST_CASE(rpc_convert_values_generatetoaddress)
BOOST_CHECK_EQUAL(result[2].get_int(), 9);
}
-BOOST_AUTO_TEST_CASE(rpc_sentinel_ping)
-{
- BOOST_CHECK_NO_THROW(CallRPC("sentinelping 1.0.2"));
- BOOST_CHECK_THROW(CallRPC("sentinelping"), std::runtime_error);
- BOOST_CHECK_THROW(CallRPC("sentinelping 2"), std::bad_cast);
-}
-
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/util.cpp b/src/util.cpp
index 036479f8aee1..a02417889283 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -641,14 +641,6 @@ boost::filesystem::path GetConfigFile(const std::string& confPath)
return pathConfigFile;
}
-boost::filesystem::path GetMasternodeConfigFile()
-{
- boost::filesystem::path pathConfigFile(GetArg("-mnconf", "masternode.conf"));
- if (!pathConfigFile.is_complete())
- pathConfigFile = GetDataDir() / pathConfigFile;
- return pathConfigFile;
-}
-
void ReadConfigFile(const std::string& confPath)
{
boost::filesystem::ifstream streamConfig(GetConfigFile(confPath));
diff --git a/src/util.h b/src/util.h
index b28bb5d945ef..323ade47cc4d 100644
--- a/src/util.h
+++ b/src/util.h
@@ -137,7 +137,6 @@ const boost::filesystem::path &GetDataDir(bool fNetSpecific = true);
boost::filesystem::path GetBackupsDir();
void ClearDatadirCache();
boost::filesystem::path GetConfigFile(const std::string& confPath);
-boost::filesystem::path GetMasternodeConfigFile();
#ifndef WIN32
boost::filesystem::path GetPidFile();
void CreatePidFile(const boost::filesystem::path &path, pid_t pid);
diff --git a/src/validation.cpp b/src/validation.cpp
index 10cfbb8d35e1..66cb705ab570 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -39,7 +39,6 @@
#include "warnings.h"
#include "instantx.h"
-#include "masternodeman.h"
#include "masternode-payments.h"
#include "evo/specialtx.h"
@@ -1828,35 +1827,7 @@ int32_t ComputeBlockVersion(const CBlockIndex* pindexPrev, const Consensus::Para
ThresholdState state = VersionBitsState(pindexPrev, params, pos, versionbitscache);
const struct BIP9DeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos];
if (vbinfo.check_mn_protocol && state == THRESHOLD_STARTED && fCheckMasternodesUpgraded) {
- if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
- auto mnList = deterministicMNManager->GetListForBlock(pindexPrev->GetBlockHash());
- auto payee = mnList.GetMNPayee();
- if (!payee) {
- continue;
- }
- } else {
- std::vector voutMasternodePayments;
- masternode_info_t mnInfo;
- if (!mnpayments.GetBlockTxOuts(pindexPrev->nHeight + 1, 0, voutMasternodePayments)) {
- // no votes for this block
- continue;
- }
- bool mnKnown = false;
- for (const auto& txout : voutMasternodePayments) {
- if (mnodeman.GetMasternodeInfo(txout.scriptPubKey, mnInfo)) {
- mnKnown = true;
- break;
- }
- }
- if (!mnKnown) {
- // unknown masternode
- continue;
- }
- if (mnInfo.nProtocolVersion < DMN_PROTO_VERSION) {
- // masternode is not upgraded yet
- continue;
- }
- }
+ // TODO implement new logic for MN upgrade checks (e.g. with LLMQ based feature/version voting)
}
if (state == THRESHOLD_LOCKED_IN || state == THRESHOLD_STARTED) {
nVersion |= VersionBitsMask(params, (Consensus::DeploymentPos)i);
diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp
index 26b08647da2b..86f374ec16a1 100644
--- a/src/validationinterface.cpp
+++ b/src/validationinterface.cpp
@@ -29,6 +29,7 @@ void RegisterValidationInterface(CValidationInterface* pwalletIn) {
g_signals.NotifyGovernanceObject.connect(boost::bind(&CValidationInterface::NotifyGovernanceObject, pwalletIn, _1));
g_signals.NotifyGovernanceVote.connect(boost::bind(&CValidationInterface::NotifyGovernanceVote, pwalletIn, _1));
g_signals.NotifyInstantSendDoubleSpendAttempt.connect(boost::bind(&CValidationInterface::NotifyInstantSendDoubleSpendAttempt, pwalletIn, _1, _2));
+ g_signals.NotifyMasternodeListChanged.connect(boost::bind(&CValidationInterface::NotifyMasternodeListChanged, pwalletIn, _1));
}
void UnregisterValidationInterface(CValidationInterface* pwalletIn) {
@@ -48,6 +49,7 @@ void UnregisterValidationInterface(CValidationInterface* pwalletIn) {
g_signals.NotifyGovernanceObject.disconnect(boost::bind(&CValidationInterface::NotifyGovernanceObject, pwalletIn, _1));
g_signals.NotifyGovernanceVote.disconnect(boost::bind(&CValidationInterface::NotifyGovernanceVote, pwalletIn, _1));
g_signals.NotifyInstantSendDoubleSpendAttempt.disconnect(boost::bind(&CValidationInterface::NotifyInstantSendDoubleSpendAttempt, pwalletIn, _1, _2));
+ g_signals.NotifyMasternodeListChanged.disconnect(boost::bind(&CValidationInterface::NotifyMasternodeListChanged, pwalletIn, _1));
}
void UnregisterAllValidationInterfaces() {
@@ -67,4 +69,5 @@ void UnregisterAllValidationInterfaces() {
g_signals.NotifyGovernanceObject.disconnect_all_slots();
g_signals.NotifyGovernanceVote.disconnect_all_slots();
g_signals.NotifyInstantSendDoubleSpendAttempt.disconnect_all_slots();
+ g_signals.NotifyMasternodeListChanged.disconnect_all_slots();
}
diff --git a/src/validationinterface.h b/src/validationinterface.h
index f5f5df31c043..78dafba43a90 100644
--- a/src/validationinterface.h
+++ b/src/validationinterface.h
@@ -20,6 +20,7 @@ class CValidationInterface;
class CValidationState;
class CGovernanceVote;
class CGovernanceObject;
+class CDeterministicMNList;
class uint256;
// These functions dispatch to one or all registered wallets
@@ -41,6 +42,7 @@ class CValidationInterface {
virtual void NotifyGovernanceVote(const CGovernanceVote &vote) {}
virtual void NotifyGovernanceObject(const CGovernanceObject &object) {}
virtual void NotifyInstantSendDoubleSpendAttempt(const CTransaction ¤tTx, const CTransaction &previousTx) {}
+ virtual void NotifyMasternodeListChanged(const CDeterministicMNList& newList) {}
virtual void SetBestChain(const CBlockLocator &locator) {}
virtual bool UpdatedTransaction(const uint256 &hash) { return false;}
virtual void Inventory(const uint256 &hash) {}
@@ -80,6 +82,8 @@ struct CMainSignals {
boost::signals2::signal NotifyGovernanceObject;
/** Notifies listeners of a attempted InstantSend double spend*/
boost::signals2::signal NotifyInstantSendDoubleSpendAttempt;
+ /** Notifies listeners that the MN list changed */
+ boost::signals2::signal NotifyMasternodeListChanged;
/** Notifies listeners of an updated transaction without new data (for now: a coinbase potentially becoming visible). */
boost::signals2::signal UpdatedTransaction;
/** Notifies listeners of a new active block chain. */
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index f1bb0b4ccec4..9dfeab8c3d3c 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -1121,10 +1121,11 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose)
}
AddToSpends(hash);
+ auto mnList = deterministicMNManager->GetListAtChainTip();
for(unsigned int i = 0; i < wtx.tx->vout.size(); ++i) {
if (IsMine(wtx.tx->vout[i]) && !IsSpent(hash, i)) {
setWalletUTXO.insert(COutPoint(hash, i));
- if (deterministicMNManager->IsProTxWithCollateral(wtx.tx, i) || deterministicMNManager->HasMNCollateralAtChainTip(COutPoint(hash, i))) {
+ if (deterministicMNManager->IsProTxWithCollateral(wtx.tx, i) || mnList.HasMNByCollateral(COutPoint(hash, i))) {
LockCoin(COutPoint(hash, i));
}
}
@@ -3984,11 +3985,13 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
// This avoids accidential spending of collaterals. They can still be unlocked manually if a spend is really intended.
void CWallet::AutoLockMasternodeCollaterals()
{
+ auto mnList = deterministicMNManager->GetListAtChainTip();
+
LOCK2(cs_main, cs_wallet);
for (const auto& pair : mapWallet) {
for (unsigned int i = 0; i < pair.second.tx->vout.size(); ++i) {
if (IsMine(pair.second.tx->vout[i]) && !IsSpent(pair.first, i)) {
- if (deterministicMNManager->IsProTxWithCollateral(pair.second.tx, i) || deterministicMNManager->HasMNCollateralAtChainTip(COutPoint(pair.first, i))) {
+ if (deterministicMNManager->IsProTxWithCollateral(pair.second.tx, i) || mnList.HasMNByCollateral(COutPoint(pair.first, i))) {
LockCoin(COutPoint(pair.first, i));
}
}
@@ -4638,11 +4641,13 @@ void CWallet::ListLockedCoins(std::vector& vOutpts)
void CWallet::ListProTxCoins(std::vector& vOutpts)
{
+ auto mnList = deterministicMNManager->GetListAtChainTip();
+
AssertLockHeld(cs_wallet);
for (const auto &o : setWalletUTXO) {
if (mapWallet.count(o.hash)) {
const auto &p = mapWallet[o.hash];
- if (deterministicMNManager->IsProTxWithCollateral(p.tx, o.n) || deterministicMNManager->HasMNCollateralAtChainTip(o)) {
+ if (deterministicMNManager->IsProTxWithCollateral(p.tx, o.n) || mnList.HasMNByCollateral(o)) {
vOutpts.emplace_back(o);
}
}